归约和总结
// 菜单里有多少道菜
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);