Java8实战读书笔记-第6章 用流收集数据

6.1 收集器简介

6.1.1 收集器用作高级归约

对流调用collect方法将对流 中的元素触发一个归约操作(由Collector来参数化)。

一般来说,Collector会对元素应用一个转换函数(很多时候是不体现任何效果的恒等转换,例如 toList),并将结果累积在一个数据结构中,从而产生这一过程的最终输出。

6.1.2 预定义收集器

6.2 归约和汇总

在需要将流项目重组成集合时,一般会使用收集器(Stream方法collect的参 数)。再宽泛一点来说,但凡要把流中所有的项目合并成一个结果时就可以用。这个结果可以是任何类 型,可以复杂如代表一棵树的多级映射,或是简单如一个整数。

6.2.1 查找流中的最大值和最小值
Optional<Dish> max = menu.stream().collect(maxBy(Comparator.comparingInt(Dish::getCalories)));
Optional<Dish> min = menu.stream().min(Comparator.comparingInt(Dish::getCalories));
6.2.2 汇总

Collectors类专门为汇总提供了一个工厂方法:Collectors.summingInt。它可接受一个把对象映 射为求和所需int的函数,并返回一个收集器;该收集器在传递给普通的collect方法后即执行我们需要 的汇总操作。

Integer result1 = menu.stream().collect(summingInt(Dish::getCalories));
Integer result2 = menu.stream().mapToInt(Dish::getCalories).sum();
6.2.3 连接字符串
String str = menu.stream().map(Dish::getName).collect(joining(","));
6.2.4 广义的归约汇总

事实上,我们已经讨论的所有收集器,都是一个可以用reducing工厂方法定义的归约过程的特殊情况而 已。Collectors.reducing工厂方法是所有这些特殊情况的一般化。可以说,先前讨论的案例仅仅是 为了方便程序员而已。

reduce方法旨在把两个 值结合起来生成一个新值,它是一个不可变的归约。

与此相反,collect方法的设计就是要改变容器,从而累积要输出的结果。

6.3 分组

Map<Boolean, List<Dish>> map = menu.stream().collect(groupingBy(Dish::isVegetarian));
6.3.1 多级分组
Map<Dish.Type, Map<String, List<Dish>>> map = menu.stream().collect(groupingBy(Dish::getType, 					groupingBy(dish -> {
        if (dish.getCalories() >= 700) {
        return "FAT";
        } else if (dish.getCalories() >= 400 && dish.getCalories() < 700) {
        return "NORMAL";
        } else {
        return "DICT";
        }
})));

在这里插入图片描述

6.3.2 按子组收集数据
// 要数一数菜单中每类菜有多少个
Map<Dish.Type, Long> map = menu.stream().collect(groupingBy(Dish::getType, counting()));
// 查找菜单中热量最高的菜肴的收集器改一改,按照菜的类型分类
Map<Dish.Type, Optional<Dish>> collect = menu.stream().collect(groupingBy(Dish::getType,maxBy(Comparator.comparing(Dish::getCalories))));
// 在上一步的基础上去掉Optional
Map<Dish.Type, Dish> collect1 = menu.stream().collect(groupingBy(Dish::getType,collectingAndThen(maxBy(Comparator.comparing(Dish::getCalories)), Optional::get)));

6.4 分区

Map<Boolean, List<Dish>> map = menu.stream().collect(partitioningBy(Dish::isVegetarian));
List<Dish> dishes = map.get(true);
6.4.1 分区的优势

分区的好处在于保留了分区函数返回true或false的两套流元素列表。
在这里插入图片描述
在这里插入图片描述

6.5 收集器接口

6.6 开发你自己的收集器以获得更好的性能

6.7 小结

以下是你应从本章中学到的关键概念。

collect是一个终端操作,它接受的参数是将流中元素累积到汇总结果的各种方式(称为收集器)。

预定义收集器包括将流元素归约和汇总到一个值,例如计算最小值、最大值或平均值。

这些收集器总 结在表6-1中。 预定义收集器可以用groupingBy对流中元素进行分组,或用partitioningBy进行分区。

收集器可以高效地复合起来,进行多级分组、分区和归约。

你可以实现Collector接口中定义的方法来开发你自己的收集器。

6.5和6.6的内容看的有些晕乎,先跳过

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值