Java8实战-函数式数据处理-Steam流之收集器

文章介绍了Java8中StreamAPI的收集器(Collector)如何用于对流进行归约操作,如查找最大值、最小值、求和、平均值等。同时,详细阐述了分组和分区功能,包括多级分组和根据条件分区,并展示了如何通过groupingBy、partitioningBy等方法实现。此外,还提到了collectingAndThen方法用于转换收集器的结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.收集器

收集器可以简洁而灵活地定义collect用来生成结果集合的标准。更具体地说,对流调用collect方法将对流中的元素触发一个归约操作(由Collector来参数化)。

案例,对一个交易列表按货币分组。

Map<Currency, List<Transaction>> transactionsByCurrencies =
 transactions.stream().collect(groupingBy(Transaction::getCurrency));

在这里插入图片描述

收集器的功能可以从Collectors类提供的工厂方法(例如groupingBy)创建的收集器。它们主要提供了三大功能:

  1. 将流元素归约和汇总为一个值
  2. 元素分组
  3. 元素分区

二.归约和汇总

  1. 查找流中的最大值和最小值

Collectors.maxByCollectors.minBy,来计算流中的最大或最小值。
这两个收集器接收一个Comparator参数来比较流中的元素。

假设你想要找出菜单中热量最高的菜。

//以创建一个Comparator来根据所含热量对菜肴进行比较,并把它传递给Collectors.maxBy
Comparator<Dish> dishCaloriesComparator = Comparator.comparingInt(Dish::getCalories); 
Optional<Dish> mostCalorieDish = menu.stream() .collect(maxBy(dishCaloriesComparator)); 
  1. 汇总

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

举个例子,样求出菜单中菜肴列表的总热量

//在遍历流时,会把每一道菜都映射为其热量,然后把这个数字累加到一个累加器(这里的初始值0)。
        List<Dish> menu = new ArrayList<>();//菜单
        menu.add(new Dish(500,"麻婆豆腐"));
        menu.add(new Dish(400,"爆炒猪肝"));
        menu.add(new Dish(400,"油焖茄子"));
        menu.add(new Dish(400,"蒜蓉龙虾"));
		int totalCalories = menu.stream().collect(summingInt(Dish::getCalories));

//更简洁可以如下写法,上行代码介绍summingInt
		int totalCalories = menu.stream().mapToInt(Dish::getCalories).sum();

Collectors.summingLongCollectors.summingDouble方法的作用完全一样,可以用于求和字段为long或double的情况。
在这里插入图片描述

汇总不仅仅是求和;还有Collectors.averagingInt,连同对应的averagingLongaveragingDouble可以计算数值的平均数:

        List<Dish> menu = new ArrayList<>();//菜单
        menu.add(new Dish(500,"麻婆豆腐"));
        menu.add(new Dish(400,"爆炒猪肝"));
        menu.add(new Dish(400,"油焖茄子"));
        menu.add(new Dish(400,"蒜蓉龙虾"));
		double avgCalories = menu.stream().collect(averagingInt(Dish::getCalories));

很多时候,可能想要得到两个或更多这样的结果,而且只需一次操作就可以完成。在这种情况下,你可以使用summarizingInt工厂方法返回的收集器。

例如,通过一次summarizing操作你可以就数出菜单中元素的个数,并得到菜肴热量总和、平均值、最大值和最小值:

        List<Dish> menu = new ArrayList<>();//菜单
        menu.add(new Dish(500,"麻婆豆腐"));
        menu.add(new Dish(400,"爆炒猪肝"));
        menu.add(new Dish(400,"油焖茄子"));
        menu.add(new Dish(400,"蒜蓉龙虾"));
        IntSummaryStatistics menuStatistics = menu.stream().collect(Collectors.summarizingInt(Dish::getCalories));
		System.out.println(menuStatistics);

这个收集器会把所有这些信息收集到一个叫作IntSummaryStatistics的类里,它提供了方便的取值(getter)方法来访问结果。打印menuStatisticobject会得到以下输出:

IntSummaryStatistics{count=4, sum=1700, min=400, average=425.000000, max=500}

同样,相应的summarizingLongsummarizingDouble工厂方法有相关的LongSummaryStatisticsDoubleSummaryStatistics类型,适用于收集的属性是原始类型long或double的情况。

  1. 连接字符串

joining工厂方法返回的收集器会把对流中每一个对象应用toString方法得到的所有字符串连接成一个字符串。

例如:

        List<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

筑梦的熊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值