Stream API
引例:
- 1 List<String> strList = Arrays.asList("zhaojigang","nana","tianya","nana");
- 2 Stream<String> streamList = strList.stream();//集合转为stream
- 3 strList = streamList.distinct().filter(str->!str.equals("tianya")).sorted(String::compareTo).collect(Collectors.toList());
- 4 strList.forEach(System.out::println);
说明:
- 第一行:创建数组并转为List
- 第二行:根据List创建stream
- 第三行:对该stream进行去重-->选择-->排序-->stream转为List
- 第四行:遍历该List
以上代码显示了stream API的方便。当然,上边的代码可以更为简洁,如下改为一行:
- Arrays.asList("zhaojigang","nana","tianya","nana").stream().distinct().filter(str->!str.equals("tianya")).sorted(String::compareTo).collect(Collectors.toList()).forEach(System.out::println);
以上代码有一个易错点:filter是选择而不是过滤,即filter是选择满足条件的元素。
一、创建Stream
三种常用API:
- 集合-->Stream:stream()
- 数组-->Stream:Stream.of(T t)或者Arrays.stream(T[] t)
- 任意元素-->Stream:Stream.of(T... values)

- 1 List<String> strList = Arrays.asList("zhaojigang","nana","tianya","nana");
- 2 Stream<String> streamList = strList.stream();//集合转为stream
- 3
- 4 String[] strArray = {"java","c++","c"};
- 5 Stream<String> streamArray = Stream.of(strArray);//数组转为Stream
- 6 Stream<String> streamArray2 = Arrays.stream(strArray);//数组转为Stream
- 7
- 8 Stream<String> streamPartArray = Arrays.stream(strArray, 0, 2);//转换部分数组,范围:[0,2)
- 9
- 10 Stream<String> streamSelf = Stream.of("python","basic","php");//任意元素

还有一种:用于产生无限流的,Stream.generate(Supplier<T> s)。
二、Stream 2 array/collection/String/map
1、stream2array
- 1 Stream<String> strStream = Stream.of("java","c++","c","python");
- 2 Object[] objectArray = strStream.toArray();//只能返回Object[]
- 3 String[] strArray = strStream.toArray(String[]::new);//构造器引用(类似于方法引用),可以返回String[]
说明:
通过构造器引用(类似于方法引用),可以构造出具体类型的数组。
2、stream2collection
- 1 List<String> strList = strStream.collect(Collectors.toList());//返回List
- 2 Set<String> strSet = strStream.collect(Collectors.toSet());//返回set
- 3 ArrayList<String> strArrayList = strStream.collect(Collectors.toCollection(ArrayList::new));//收集到指定的List集合,例如收集到ArrayList
说明:
通过构造器引用,可以构造出具体类型的集合。
3、将stream中的元素拼接起来(joining()、joining(","))
- 1 Stream<String> strStream = Stream.of("java","c++","c","python");
- 2 String str = strStream.collect(Collectors.joining());//将所有字符串拼接起来,结果:javac++cpython
- 3 System.out.println(str);
- 4
- 5 String str2 = strStream.collect(Collectors.joining(","));//将所有字符串拼接起来,中间用","隔开,结果:java,c++,c,python
- 6 System.out.println(str2);
4、stream2map(toMap、toConcurrentMap)

- 1 Stream<String> strStream = Stream.of("java","c++","c","python");
- 2 Map<String, Integer> map1 = strStream.collect(Collectors.toMap(Function.identity(), (x)->0));
- 3 //Function.identity()-->返回strStream中的元素,toMap方法的我两个参数都是Function接口型的,所以第二个参数即使只放0,也不能直接写作0,可以使用如上的方式进行操作
- 4
- 5 for(String key : map1.keySet()){
- 6 System.out.println("key:"+key+"->"+"value:"+map1.get(key));
- 7 }
- 8 //结果
- 9 /*
- 10 key:python->value:0
- 11 key:c++->value:0
- 12 key:c->value:0
- 13 key:java->value:0
- 14 */

说明:
- toMap-->stream转为map
- Function.identity()-->返回stream中的元素
如果key重复的话,这时就会出现问题"duplicate key",采用如下方式解决(增加第三个参数):
- 1 Stream<String> strStream = Stream.of("java","c++","c","python","java");
- 2 Map<String, Integer> map1 = strStream.collect(Collectors.toMap(Function.identity(), //key
- 3 (x)->0, //value
- 4 (existingValue, newValue) -> existingValue));//如果key重复,取旧值
需要指定返回map的具体类型(增加第四个参数)。
- 1 Map<String, Integer> map1 = strStream.collect(Collectors.toMap(Function.identity(), //key
- 2 (x)->0, //value
- 3 (existingValue, newValue) -> existingValue,//如果key重复,取旧值
- 4 TreeMap::new));//返回TreeMap
注意:每一个toMap就会对应一个相应的toConcurrentMap
5、groupingBy partitioningBy

- 1 /***************************groupingBy partitioningBy**************************/
- 2 Stream<Locale> localeStream = Stream.of(Locale.getAvailableLocales());
- 3 Map<String, List<Locale>> country2localeList = localeStream.collect(Collectors.groupingBy(Locale::getCountry));//根据国家分组,groupBy的参数是分类器
- 4 List<Locale> locales = country2localeList.get("CH");
- 5
- 6 Map<String, Set<Locale>> country2localeSet = localeStream.collect(Collectors.groupingBy(Locale::getCountry, Collectors.toSet()));//根据国家分组,groupBy的参数是分类器,返回set
- 7 Set<Locale> localeSet = country2localeSet.get("CH");
- 8
- 9 Map<Boolean, List<Locale>> country2locales = localeStream.collect(Collectors.partitioningBy(locale->locale.getLanguage().equals("en")));//分成两组,一组为true(即语言是en的),一组为false(即语言不是en的)
- 10 List<Locale> trueLocale = country2locales.get(true);

三、filter(Predicate p)
注意:是选择而非过滤。
- 1 Stream<String> streamSelf = Stream.of("python","basic","php");
- 2 streamSelf.filter(str->str.startsWith("p")).forEach(System.out::println);
注意:
- stream也是可以foreach的,没必要一定要转化成集合再foreach
更好的写法可能是下边这种:
- 1 Predicate<String> startCondition = str->str.startsWith("p");
- 2 streamSelf.filter(startCondition).forEach(System.out::println);
说明:将条件(通常是lambda表达式)抽取出来。这种方式在多个条件的情况下比较清晰。
注意:函数式接口 = lambda表达式 (即lambda表达式只能返回为函数式接口)
- 1 Stream<String> s = Stream.of("java1","java3","java","php12");
- 2 Predicate<String> condition1 = str->str.length()==5;//条件1
- 3 Predicate<String> condition2 = str->str.startsWith("j");//条件2
- 4 s.filter(condition1.and(condition2)).forEach(System.out::println);//and条件
说明:
多条件运算:and or
四、map(Function mapper)
作用:对流中的每一个元素进行操作。
- 1 Stream<String> streamSelf = Stream.of("python","basic","php");
- 2 streamSelf.map(String::toUpperCase).forEach(System.out::println);
说明:将流内的每一个String全部转换为了大写。
五、reduce
作用:对stream中的每一个元素做聚合操作。

- 1 Stream<Integer> reduceStream = Stream.of(1,2,3,4,5);
- 2 Optional<Integer> sumOption = reduceStream.reduce((x,y)->x+y);//计算1+2+3+4+5,即对元素中的元素进行聚合计算,而map是对元素中的每一个元素分别计算(注意:如果stream为null的话,就会产生无效的结果,需要使用Optional接收)
- 3 //Optional<Integer> sumOption = reduceStream.reduce(Integer::sum);//计算1+2+3+4+5,即对元素中的元素进行聚合计算,而map是对元素中的每一个元素分别计算
- 4
- 5 Integer result = reduceStream.reduce(0, Integer::sum);//0为标识值,即计算:0+1+2+。。+5,如果整个stream为null,就返回标识值。
- 6 System.out.println(result);

注意:以上是reduce的简单形式,即内联函数是(T,T)->T,即返回值和参数类型是一样的,返回值和参数类型不同的场景需要自己编写函数(用的较少)
六、Optional
两种用法:
- ifPresent(xxx):存在的就执行xxx,不存在就什么都不执行
- orElse(xxx):存在就返回存在的值,不存在就返回xxx(可以理解为是默认值)

- 1 Stream<String> optionalStream = Stream.of("java","python","basic");
- 2 Optional<String> optionValue = optionalStream.filter(str->str.startsWith("p")).findFirst();
- 3 optionValue.ifPresent(str->System.out.println(str));//if optionalValue为true,即str存在,则输出str,当然也可以使用如下
- 4 String str = optionValue.orElse("xxx");//如果optionValue为false,即不存在以p开头的字符串时,使用"xxx"来替代
- 5 System.out.println(str);

七、limit skip contact
1、limit(long size)
作用:截取stream的前size个元素。
- 1 Stream<String> streamSelf = Stream.of("python","basic","php");
- 2 streamSelf.limit(2).forEach(System.out::println);//截取前两个
2、skip(long size)
作用:跳过stream的钱size个元素
- 1 Stream<String> streamSelf = Stream.of("python","basic","php");
- 2 streamSelf.skip(2).forEach(System.out::println);//跳过前两个
3、contact(Stream<T>,Stream<T>)
作用:拼接两个stream
- 1 Stream<String> streamSelf = Stream.of("python","basic","php");
- 2 Stream<String> streamSelf2 = Stream.of("python2","basic2","php2");
- 3 Stream.concat(streamSelf, streamSelf2).forEach(System.out::println);
八、聚合函数 count max min findFirst findAny anyMatch allMatch noneMatch
- 1 Stream<String> streamSelf = Stream.of("python","basic","php","b");
- 2 System.out.println(streamSelf.count());//计算流中的元素个数
- 3 Optional<String> largest = streamSelf.max(String::compareToIgnoreCase);//寻找最大值
- 4 if(largest.isPresent()){
- 5 System.out.println(largest.get());
- 6 }
说明:min函数也一样。
注意:Optional的使用,上边的是最差的一种形式,见"六"。

- 1 Optional<String> firstMatch = streamSelf.filter(str->str.startsWith("b")).findFirst();//寻找第一个符合条件的元素
- 2 firstMatch.ifPresent(System.out::println);//这是Optional的第一种用法
- 3
- 4 Optional<String> anyMatch = streamSelf.parallel().filter(str->str.startsWith("b")).findAny();//返回集合中符合条件的任意一个元素,对于并行处理非常好(因为多个线程只要有一个线程找到了,整个计算就会结束)
- 5 if(anyMatch.isPresent()){
- 6 System.out.println(anyMatch.get());//这里的结果可能是b,有可能是basic
- 7 }
- 8
- 9 boolean isAnyMatch = streamSelf.parallel().anyMatch(str->str.startsWith("c"));//集合中是否有一个满足条件
- 10 System.out.println(isAnyMatch);
- 11
- 12 Stream<String> streamSelf3 = Stream.of("basic","b");
- 13 boolean isAllMatch = streamSelf3.parallel().allMatch(str->str.startsWith("b"));//集合中是否所有元素都满足条件
- 14 System.out.println(isAllMatch);
- 15
- 16 boolean isAllNotMatch = streamSelf.parallel().noneMatch(str->str.startsWith("p"));//集合中是否没有一个元素满足条件
- 17 System.out.println(isAllNotMatch);

注意:
- optional的最佳用法:ifPresent()-->如果有就输出,如果没有,什么都不做
- parallel():将stream转为并行流,并行流的使用一定要注意线程安全
九、原始类型流
- IntStream:int、short、char、byte、boolean
- LongStream:long
- DoubleStream:double、float
Stream API的更多相关文章
- Java 8 Stream API详解--转
原文地址:http://blog.csdn.net/chszs/article/details/47038607 Java 8 Stream API详解 一.Stream API介绍 Java8引入了 ...
- Atitit 实现java的linq 以及与stream api的比较
Atitit 实现java的linq 以及与stream api的比较 1.1. Linq 和stream api的关系,以及主要优缺点1 1.2. Linq 与stream api的适用场景1 1. ...
- Java 使用 Stream API 筛选 List
前言 上课的时候看到老师用迭代器来遍历 List 中的元素的时候,我的内心是极其嫌弃的,这种迭代方法不能直接访问当前的元素,而且写起来也麻烦.于是上网查了查 Java 有没有类似于 Linq 的东西, ...
- Upgrading to Java 8——第四章 The Stream API
在这章中我们将学习Stream API,在JDK 8 中的一项新的特性.为了理解这一章的主题,你需要知道如何使用Lambda表达式和java.util.function里的预定义的函数式接口. 一个S ...
- Java 8: Lambdas和新的集合Stream API
Lambda是Java8的主要特色,Java 8: Lambdas & Java Collections | zeroturnaround.com一文介绍了使用Lambda集合处理大量数据的方 ...
- Java 8 Stream API Example Tutorial
Stream API Overview Before we look into Java 8 Stream API Examples, let’s see why it was required. S ...
- 第二章 Stream API
引例: 1 List<String> strList = Arrays.asList("zhaojigang","nana","tiany ...
- Java Stream API入门篇
本文github地址 你可能还没意识到Java对函数式编程的重视程度,看看Java 8加入函数式编程扩充多少类就清楚了.Java 8之所以费这么大功夫引入函数式编程,原因有二: 代码简洁,函数式编程写 ...
- Java Stream API性能测试
已经对Stream API的用法鼓吹够多了,用起简洁直观,但性能到底怎么样呢?会不会有很高的性能损失?本节我们对Stream API的性能一探究竟. 为保证测试结果真实可信,我们将JVM运行在-ser ...
- Java 8新特性:新语法方法引用和Lambda表达式及全新的Stream API
新语法 方法引用Method references Lambda语法 Lambda语法在AndroidStudio中报错 Stream API 我正参加2016CSDN博客之星的比赛 希望您能投下宝贵 ...
随机推荐
- 【python-opencv】18-图像梯度+图像边界
效果图: *一阶导数与Soble算子 *二阶导数与拉普拉斯算子 定义:把图片想象成连续函数,因为边缘部分的像素值是与旁边像素明显有区别的,所以对图片局部求极值,就可以得到整幅图片的边缘信息了. 不过图 ...
- Python装饰器与面向切面编程(转)
add by zhj: 装饰器的作用是将代码中可以独立的功能独立出来,实现代码复用,下面那个用于统计函数运行时间的装饰器就是很好的例子,我们不用修改原有的函数和调用原有函数的地方,这遵循了开闭原则.装 ...
- android(五)----使用WakeLock使Android应用程序保持后台唤醒
在使用一些产品列如微信.QQ之类的,如果有新消息来时,手机屏幕即使在锁屏状态下也会亮起并提示声音,这时用户就知道有新消息来临了. 但是,一般情况下手机锁屏后,Android系统为了省电以及减少CPU消 ...
- 【PHP】PHP初学者的学习线路
先来看下PHP初学者的学习线路: (1) 熟悉HTML/CSS/JS等网页基本元素,完成阶段可自行制作简单的网页,对元素属性相对熟悉. (2) 理解动态语言的概念和运做机制,熟悉基本的PHP语法. ( ...
- (3.11)mysql基础深入——mysql文件分类与配置文件管理
(3.11)mysql基础深入——mysql文件分类与管理 关键词:mysql配置文件,mysql参数文件,mysql中的my.cnf 目录:mysql数据库文件分类: [1]参数文件:my.cnf ...
- 迁移到 Linux :入门介绍 | Linux 中国
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/F8qG7f9YD02Pe/article/details/79001952 这个新文章系列将帮你从其 ...
- 当前数据库普遍使用wait-for graph等待图来进行死锁检测
当前数据库普遍使用wait-for graph等待图来进行死锁检测 较超时机制,这是一种更主动的死锁检测方式,innodb引擎也采用wait-for graph SQL Server也使用wait-f ...
- 在centos7下安装svn
SVN的安装 yum install subversion 服务端命令 1. svnserver - 控制svn系统服务的启动等 2. svnadmin - 版本库的创建/导出/导入/删除等 3. s ...
- Razor中的@:和语法
用Razor实现流畅编程 Razor尽量减少编写一个视图模板需要敲入的字符数,实现快速流畅的编程工作流.与大部分模板的语法不同,你不必在HTML中为了明确地标记出服务模块 的开始和结束而中断编程.Ra ...
- QC质量管理七大手法
1.层别法 层别法就是将大量有关某一特定主题的观点.意见或想法按组分类,将收集到的大量的数据或资料按相互关系进行分组,加以层别.层别法一般和柏拉图.直方图等其它七大手法结合使用,也可单独使用. 2.查 ...