使用流收集数据
流的特征
流最重要的几个特征。
-
流并不存储元素。它们只处理存放在数据源(数据结构、文件等)中的元素。
- 流不可重用。
- 流可对数据进行延迟处理。
- 流操作不能修改流的源。
- 流允许你进行链式操作,因此一项操作的输出是下一项操作的输入。
流的三要素
流由下述三个要素构成。
-
生成流元素的源。
- 0 个或多个中间操作,这些操作可以产生输出,形成另一个流。
- 一个可以产生结果的末端操作,该结果既可以是一个简单对象、数组、Colletion、Map,也可以是其他的东西。
collect() 方法
collect() 方法可对流的元素进行转换和分组,生成一个含有流最终结果的新数据结构。
可以使用多达三种不同的数据类型:
- 一种输入数据类型,即来自流的输入元素的数据类型;
- 一种中间数据类型,用于在 collect() 方法运行过程中存放元素;
- 一种输出数据类型,它由 collect() 方法返回。
collect() 方法有两个版本。
collect()第一个版本
第一个版本接收下述三种函数型参数。
-
Supplier 函数:
这是一个创建中间数据类型对象的函数。
如果使用顺序流,该方法会被调用一次。
如果使用并行流,该方法会被调用多次,而且每次都必须产生一个新对象。 - Accumulator 函数:
调用该函数可以处理输入元素,并且在中间数据结构中存放该元素。 - Combiner 函数:
调用该函数可以将两个中间数据结构合二为一。
该函数只有在处理并行流时才会被调用。
这个版本的 collect() 方法用到了两种不同的数据类型:
- 来自流的元素的输入数据类型
- 用于存放中间元素并返回最终结果的中间数据类型。
collect()第二个版本
collect() 方法的第二个版本接收一个实现 Collector 接口的对象。
可以自己实现该接口,但是使用 Collector.of() 静态方法更容易。
该方法的参数如下所示。
-
Supplier:
该函数创建了一个中间数据类型的对象,其用法参照前面的介绍。 - Accumulator:
调用该函数可以处理一个输入元素,如果必要还可对该元素进行转换,并且将其存放在中间数据结构中。 - Combiner:
调用该函数可以将两个中间数据结构合并成一个,用法参照前面的介绍。 - Finisher:
如果需要进行最终的转换或者计算,调用该函数可以将中间数据结构转换成最终 的数据结构。 - Characteristics:
可以使用这个最后的变量参数表明所创建的收集器的一些特征。
预定义的收集器
Java 在 Collector 工厂类中提供了一些预定义的收集器。
可以通过这些收集器的静态方法获得这些收集器。
如下是其中的一些方法。
-
averagingDouble() 、 averagingInt() 和 averagingLong() :
这些方法返回一个收集器,能够计算 double 、 int 或者 long 型函数的算术平均值。 - groupingBy() :
该方法返回一个收集器,使你能够按照其对象的某一属性对流的元素进行分组,生成一个 Map,其键为所选定属性的值,而其值为具有某一确定值的对象列表。 - groupingByConcurrent() :
这和前一个方法相似,只是有两点不同。
第一个不同点在于该方法在并行模式下比 groupingBy() 方法更快,但是在顺序模式下却更慢。
第二个(也是最重要的)不同点在于 groupingByConcurrent() 函数是一个无序的收集器。不能保证列表中项的顺序和其在流中的顺序相同。而 groupingBy() 收集器则能够保证排序。 - joining() :
该方法返回一个 Collector 工厂类,将输入元素串联为一个字符串。 - partitioningBy() :
该方法返回一个 Collector 工厂类,基于某个谓词的结果对输入元素进行划分。 - summarizingDouble() 、 summarizingInt() 和 summarizingLong() :
这些方法返回一个 Collector 工厂类,计算输入元素的汇总统计值。 - toMap() :
该方法返回一个 Collector 工厂类,使你可以基于两个映射函数将输入元素转换为一个 Map。 - toConcurrentMap() :
该方法与前一个类似,只是以并发方式工作。
在不考虑定制归并器的情况下, toConcurrentMap() 只是在并行流的情况下较快。
与 groupingByConcurrent()方法一样,这也是一个无序收集器,而 toMap() 则采用相遇时的排序执行转换。 - toList() :
该方法返回一个 Collector 工厂类,将输入元素存放到一个列表中。 - toCollection() :
该方法使你能够按照相遇时的排序将输入元素累加到一个新的 Collection 工厂类( TreeSet 、 LinkedHashSet 等)。
该方法接收一个创建该 Collection 的 Supplier 接口实现作为参数。 - maxBy() 和 minBy() :
该方法返回一个 Collector 工厂类,根据以参数传递的比较器产生最大元素和最小元素。 - toSet() :
该方法返回一个 Collector ,它将输入元素存放到一个集合。