Java8中提供了Collectors類來做收集器。以下介紹都是使用流中的collect方法接收Collector接口的實現(xiàn)。
一、規(guī)約和匯總
- 查找流中的最大值和最小值
//Collectors提供了maxBy和minBy來計算流中的最大值和最小值
Comparator<Dish> dishCaloriesComparator = Comparator.comparingInt(Dish::getCalories);
Optional<Dish> mostCalorieDish = menu.stream()
.collect(maxBy(dishCaloriesComparator));
匯總
提供了Collectors.summingInt、Collectors.summingLong、Collectors.summingDouble來實現(xiàn)累加操作。
還有Collectors.averagingInt來計算平均,Collectors.summarizingInt統(tǒng)計綜合值等。連接字符串
Collectors.joining()或者Collectors.joining(“字符”)廣義的規(guī)約匯總
Collectors.reducing,與reduce方法相比,這種方法更易于并行處理,詳情見《Java8實戰(zhàn)》P117
二、分組
Collectors.groupingBy工廠方法返回的收集器可以進行分組,分組的結(jié)果為一個Map。

Collectors.groupingBy分組
案例:整數(shù)列表根據(jù)模 5 的值分組求和。
Map<Integer, Integer> groupByMod5 = list.stream()
.collect(groupingBy(i -> i % 5, summingInt(Integer::intValue)));
三、分區(qū)
分區(qū)是分組的特殊情況:由一個謂詞(返回一個布爾值的函數(shù))作為分區(qū)函數(shù),它稱為分區(qū)函數(shù)。返回結(jié)果Map中包含true一組和false一組。分區(qū)函數(shù)為:Collectors.partitioningBy。

Collectors.partitioningBy分區(qū).png
案例:整數(shù)列表分奇偶求和。
Map<Boolean, Integer> partedByEven = list.stream()
.collect(partitioningBy(i -> i % 2 == 0, summingInt(Integer::intValue)));
System.out.println("集合偶數(shù)和為:" + partedByEven.get(true));
System.out.println("集合奇數(shù)和為:" + partedByEven.get(false));
四、收集器接口
//在下面的接口中:
//T是流中要收集的項目的泛型,A是累加器的類型,累加器是在收集過程中用于累計部分結(jié)果的對象。
//R是收集操作得到的對象(通常但并不一定是集合)類型
public interface Collector<T, A, R> {
//建立新的容器,返回一個結(jié)果為空的Supplier,即無參數(shù)函數(shù)
Supplier<A> supplier();
//將元素添加到容器,返回執(zhí)行歸約操作的函數(shù)
BiConsumer<A, T> accumulator();
//對容器結(jié)果應(yīng)用最終轉(zhuǎn)換
Function<A, R> finisher();
//合并兩個結(jié)果的容器
BinaryOperator<A> combiner();
//返回一個不可變的Characteristics集合,其定義了收集器的行為
Set<Characteristics> characteristics();
}
補充:Characteristics是一個包含三個項目的枚舉。
- UNORDERED——歸約結(jié)果不受流中項目的遍歷和累積順序的影響。
- CONCURRENT——accumulator函數(shù)可以從多個線程同時調(diào)用,且該收集器可以并行歸約流。如果收集器沒有標(biāo)為UNORDERED,那它僅在用于無序數(shù)據(jù)源時才可以并行歸約。
- IDENTITY_FINISH——這表明完成器方法返回的函數(shù)是一個恒等函數(shù),可以跳過。這種情況下,累加器對象將會直接用作歸約過程的最終結(jié)果。這也意味著,將累加器A不加檢 15 查地轉(zhuǎn)換為結(jié)果R是安全的。
自定義接口實現(xiàn):

ToListCollector接口實現(xiàn)