歸約和總結
// 菜單里有多少道菜
menu.stream().count();
// 熱量最高的菜
Comparator<Dish> calComparator = Comparator.comparingInt(Dish::getCalories);
menu.stream().collect(maxBy(calComparator));
// 匯總
menu.stream().collect(summingInt(Dish::getCalories));
// 平均數
menu.stream().collect(averagingInt(Dish::getCalories));
// 連接字符串
String s = menu.stream().map(Dish::getName).collect(joining(","));
// 廣義上的歸約總結
// 3個參數版本: 初始值、轉換函數、歸約函數
menu.stream().collect(reducing(0, Dish::getCalories, (i, j) -> i + j));
// 1個參數版本
menu.stream().collect(reducing((d1, d2) -> d1.getCalories() > d2.getCalories() ? d1 : d2));
分組
// 按菜的熱量分類
Map<CaloricLevel, List<Dish>> dishByType = menu.stream().collect(groupingBy(dish -> {
if (dish.getCalories() <= 400) return CaloricLevel.DIET;
else return CaloricLevel.FAT;
}));
// 先按類型再按熱量分類
Map<Dish.Type, Map<CaloricLevel, List<Dish>>> dishesByTypeCaloric =
groupingBy(Dish::getType,
groupingBy( dish - > {
if (dish.getCalories() <= 400) return CaloricLevel.DIET;
else return CaloricLevel.FAT;
})));
// 轉換收集器的結果類型
Map<Dish.Type, Dish> maxCaloricByType =
menu.stream().collect(groupingBy(Dish::getType,
// //轉換函數collectingAndThen,接受2個參數,要轉換的收集器maxBy,和轉換函數Optional::get
collectingAndThen(maxBy(comparingInt(Dish::getCalories)),
Optional::get));
// 組合2個收集器
Map<Dish.Type, Dish> maxCaloricByType =
menu.stream().collect(groupingBy(Dish::getType,
// mapping方法接受2個參數:一個是對流中元素做變化的函數,另一個是收集器負責收集函數結果
mapping( dish -> {if ...else }, toSet()
)));
分區
// 分區是分組的特殊情況,返回boolean值的分組就是分區
// 例如對素食和非素食按類型分組,得到二級Map
Map<Boolean, Map<Dish.Type, List<Dish>>> vegetarianDishesByType =
menu.stream().collect(
partitioningBy(Dish::isVegetarian,
groupingBy(Dish::getType)));
收集器接口
// T是流的泛型,A是累加器的類型,R是收集操作得到的對象類型
public interface Collector<T, A, R> {
// 建立一個新的結果容器
Supplier<A> supplier();
// 例如:
public Supplier<List<T>> supplier() {
return ArrayList::new;
}
// 將元素添加到結果容器
BiConsumer<A, T> accumulator();
// 例如:
public BiConsumer<List<T>, T> accumulator() {
return (list, item) -> list.add(item);
}
// 對結果容器應用最終轉換
Function<A, R> finisher();
// 例如:
public Function<List<T>, List<T>> finisher() {
return Function.identity();
}
// 合并兩個結果容器
BinaryOperator<A> combiner();
// 例如:
public BinaryOperator<List<T>> combiner() {
return (list1, list2) -> {
list1.addAll(list2);
return list1;
}
}
// 返回枚舉集合:UNORDERED, CONCURRENT, IDENTITY_FINISH
Set<Characteristics> characteristics();
}
可以不用實現Collector進行自定義收集
menuStream.collect(ArrayList::new, List::add, List::addAll);