Java 8 中,引入了流(Stream)的概念,注意这个流和 IO 中的流并不一样,它代表的是顺序输出的任意Java对象实例。
Stream的特点:
-
可以“存储”有限个或无限个元素。这里的存储打了个引号,是因为元素有可能已经全部存储在内存中,也有可能是根据需要实时计算出来的。
-
一个Stream可以轻易地转换为另一个Stream,而不是修改原Stream本身。
-
真正的计算通常发生在最后结果的获取,也就是惰性计算。惰性计算的特点是:一个Stream转换为另一个Stream时,实际上只存储了转换规则,并没有任何计算发生。
集合接口有两个方法来生成流:
-
stream() − 为集合创建串行流。
-
parallelStream() − 为集合创建并行流。
常用方法:
- map 将一个Stream转换为另一个Stream
- filter 对Stream中的元素进行一一测试,不满足条件的就被过滤掉
- reduce 聚合方法,将Stream中的所有元素按照聚合函数聚合成一个结果
- collect(Collectors.toList()) 由Stream里的值生成一个列表
- sorted 排序
- distinct 去重
- skip limit 截取
- flatMap 把Stream的每个元素映射为Stream,然后合并成一个新的Stream
其他聚合操作:count(),max(),min(),sum(),average();
// 计算person列表中年龄大于20的人数
long count = persons.stream()
.filter(person -> person.getAge() > 20)
.count();
Note:
聚合操作是真正需要从Stream请求数据的,对一个Stream做聚合计算后,结果就不是一个Stream,而是一个其他的Java对象。
并行操作
对于一个Stream,调用它的 parallel() 方法就能让其拥有并行操作的能力。对于一个集合,调用 parallelStream() 就能立即获得一个拥有并行能力的流。
// 求所有字符串长度之和
int sumSize = Stream.of("Apple", "Banana", "Orange", "Pear")
.parallel()
.map(s -> s.length())
.reduce(Integer::sum)
.get();
assertEquals(sumSize, 21);
Note:
以上这段代码所花的时间,很可能比不加上 parallel() 方法花的时间更长。这是因为数据并行化会先对数据进行分块,然后对每块数据开辟线程进行运算,这些地方会花费额外的时间。并行化操作只有在 数据规模比较大 或者 数据的处理时间比较长 的时候才能体现出优势,所以并不是每个地方都需要让数据并行化,应该具体问题具体分析。