reducing简介

reducing 是一个收集器(操作),从字面意义上可以理解为“减少操作”:输入多个元素,在一定的操作后,元素减少。

reducing 有多个重载方法,其中一个方法如下:

public static <T> Collector<T,?,Optional<T>> reducing(BinaryOperator<T> op)

以上方法,JDK对其的描述是:

Returns a Collector which performs a reduction of its input elements under a specified BinaryOperator. The result is described as an Optional. (返回一个收集器,该收集器在指定的二进制操作符下执行其输入元素的减少。结果被描述为可选的 <T>。)

reducing的应用

reducing 是一个非常有用的收集器,可以用在多层流、下游数据分组或分区等场合。

下面是一个例子:
给定一组 Person 对象,每个 Person 都有 city(所在城市)和 height(身高)属性,编写一个程序,统计出每个不同的城市最大、最小身高值。

import java.util.*;
import java.util.function.BinaryOperator;import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.reducing;/*** ReducingDemo** @author Zebe*/
public class ReducingDemo {/*** 运行入口** @param args 运行参数*/public static void main(String[] args) {List<Person> personList = getPersonList(1000000);functionStyle(personList);normalStyle(personList);}/*** 函数式编程风格(3行处理代码)* @param personList Person 列表*/private static void functionStyle(List<Person> personList) {long start = System.currentTimeMillis();// 创建一个比较器,取名为 byHeight (通过高度来比较)Comparator<Person> byHeight = Comparator.comparingInt(Person::getHeight);// 创建一个归一收集器Map<City, Optional<Person>> tallestByCity = personList.stream().collect(groupingBy(Person::getCity, reducing(BinaryOperator.maxBy(byHeight))));long usedTime = System.currentTimeMillis() - start;printResult("函数式编程风格", personList.size(), usedTime, tallestByCity);}/*** 普通编程风格(20行处理代码)* @param personList Person 列表*/private static void normalStyle(List<Person> personList) {long start = System.currentTimeMillis();// 创建一个结果集Map<City, Optional<Person>> tallestByCity = new HashMap<>();// 第一步:找出所有的不同城市Set<City> cityList = new HashSet<>();for (Person person : personList) {if (!cityList.contains(person.getCity())) {cityList.add(person.getCity());}}// 第二部,遍历所有城市,遍历所有人找出每个城市的最大身高for (City city : cityList) {int maxHeight = 0;Person tempPerson = null;for (Person person : personList) {if (person.getCity().equals(city)) {if (person.getHeight() > maxHeight) {maxHeight = person.getHeight();tempPerson = person;}}}tallestByCity.put(city, Optional.ofNullable(tempPerson));}long usedTime = System.currentTimeMillis() - start;printResult("普通编程风格", personList.size(), usedTime, tallestByCity);}/*** 获取Person列表* @param numbers 要获取的数量* @return 返回指定数量的 Person 列表*/private static List<Person> getPersonList(int numbers) {// 创建城市final City cityChengDu = new City("成都");final City cityNewYork = new City("纽约");List<Person> people = new ArrayList<>();// 创建指定数量的Person,并指定不同的城市和相对固定的身高值for (int i = 0; i < numbers; i++) {if (i % 2 == 0) {// 成都最大身高185people.add(new Person(cityChengDu, 185));} else if (i % 3 == 0) {people.add(new Person(cityChengDu, 170));} else if (i % 5 == 0) {// 成都最小身高160people.add(new Person(cityChengDu, 160));} else if (i % 7 == 0) {// 纽约最大身高200people.add(new Person(cityNewYork, 200));} else if (i % 9 == 0) {people.add(new Person(cityNewYork, 185));} else if (i % 11 == 0) {// 纽约最小身高165people.add(new Person(cityNewYork, 165));} else {// 默认添加纽约最小身高165people.add(new Person(cityNewYork, 165));}}return people;}/*** 输出结果* @param styleName 风格名称* @param totalPerson 总人数* @param usedTime 计算耗时* @param tallestByCity 统计好最大身高的城市分组MAP*/private static void printResult(String styleName, long totalPerson, long usedTime, Map<City, Optional<Person>> tallestByCity) {System.out.println("\n" + styleName + ":计算 " + totalPerson + " 个人所在不同城市最大身高的结果如下:(耗时 " + usedTime + " ms)");tallestByCity.forEach((city, person) -> {person.ifPresent(p -> System.out.println(city.getName() + " -> " + p.getHeight()));});}}

Person类

/*** Person** @author Zebe*/
public class Person {/*** 所在城市*/private City city;/*** 身高*/private int height;/*** 构造器* @param city 所在城市* @param height 身高*/public Person(City city, int height) {this.city = city;this.height = height;}public City getCity() {return city;}public void setCity(City city) {this.city = city;}public int getHeight() {return height;}public void setHeight(int height) {this.height = height;}
}

City类

/*** City** @author Zebe*/
public class City {/*** 城市名*/private String name;/*** 构造器* @param name 城市名*/public City(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

注:以上代码如果要计算最小值、平均值,将 maxBy 换成 minBy 就可以了。

输出结果

程序输出结果如下:

函数式编程风格:计算 1000000 个人所在不同城市最大身高的结果如下:(耗时 149 ms)
成都 -> 185
纽约 -> 200普通编程风格:计算 1000000 个人所在不同城市最大身高的结果如下:(耗时 82 ms)
成都 -> 185
纽约 -> 200

可以看出,函数式编程的效率不一定会比普通编程效率更高,甚至相对要慢一点,但是,函数式编程的好处在于:

  • 把参数作为一个函数,而不是值,实现了只有在需要的时候才计算(惰性求值)。
  • 使用 lambda 表达式能够简化程序表达的含义,使程序更简洁明了。

本文原文地址:https://blog.csdn.net/zebe1989/article/details/82855511

Java8 - 定制归一化收集器(reducing)得到自定义结果集相关推荐

  1. java8默认内存收集器_使用正确的垃圾收集器将Java内存使用量降至最低

    java8默认内存收集器 大小对于软件至关重要. 很明显,与大的整体方法相比,在微服务体系结构中使用小片段具有更多优势. 最新的Java版本的Jigsaw有助于分解旧应用程序或从头开始构建新的云原生应 ...

  2. java8自定义收集器_使用自定义收集器进行Java 8分组?

    我有以下课程. class Person { String name; LocalDate birthday; Sex gender; String emailAddress; public int ...

  3. 流集数据收集器最新消息

    最新消息 3.10.0 中的新增功能 数据收集器版本 3.10.0 包括以下新功能和增强功能: 起源 此版本包括以下新源: Groovy 脚本 - 运行 Groovy 脚本以创建数据收集器记录. 脚本 ...

  4. Java虚拟机(三)--------GC算法和收集器

    如何判断对象可以被回收 堆中几乎放着所有的对象实例,对堆垃圾回收前的第一步就是要判断哪些对象已经死亡(即不能再被任何途径使用的 对象) 引用计数法 给对象添加一个引用计数器,每当有一个地方引用,计数器 ...

  5. GC算法与GC收集器

    Java相比于C++这样语言,除了跨平台的特性外,最突出的特点就是垃圾回收机制.C++的开发人员还需要手动分配和回收内存,但JVM直接承担起了垃圾回收的重任,开发人员可以专注于业务开发,不需要再去关心 ...

  6. (七)JVM成神路之GC分代篇:分代GC器、CMS收集器及YoungGC、FullGC日志剖析

    引言 在<GC基础篇>中曾谈到过分代以及分区回收的概念,但基础篇更多的是建立在GC的一些算法理论上进行高谈阔论,而本篇则重点会对于分代收集器的实现进行全面详解,其中会涵盖串行收集器.并行收 ...

  7. Java8 Stream 自定义收集器Collector

    在之前的例子中,我们都是使用Collectors的静态方法提供的CollectorImpl,为接口Collector<T, A, R>的一个实现类,为了自定义我们自己的Collector, ...

  8. 矩阵累积相乘 java_累积:轻松自定义Java收集器

    矩阵累积相乘 java Accumulative是针对Collector<T, A, R>的中间累积类型A提出的接口Collector<T, A, R>以使定义自定义Java ...

  9. 累积:轻松自定义Java收集器

    Accumulative是针对Collector<T, A, R>的中间累积类型A提出的接口Collector<T, A, R>以使定义自定义Java Collector更加容 ...

  10. Stream流与Lambda表达式(四) 自定义收集器

    一.自定义SetCustomCollector收集器 package com.java.design.Stream.CustomCollector;import java.util.*; import ...

最新文章

  1. Java工具类之:包装类
  2. 从R-CNN到YOLO,2020 图像目标检测算法综述
  3. 笔记 | 深入理解深度学习语义分割
  4. Java 编程下的同步代码块
  5. 下列数据类型中python不支持的是_ 下列选项中 ,Python 不支持的数据类型有 ( ) 。_学小易找答案...
  6. 倒计时 | 7.24 阿里云 Serverless Developer Meetup 杭州站报名火热进行中!
  7. linux下SD卡烧录程序
  8. 为什么有人说开车时,最能看出一个人的情商和潜力?
  9. Linux基础(2)-基础命令和bash的基础特性(1)
  10. VueRouter基础知识记录1
  11. 给Activity设置背景色
  12. 锐捷校园网环境下使用虚拟机上网
  13. 2022爱分析・汽车行业数字化实践报告
  14. 《模拟电子技术》–童诗白
  15. cad导出jpg格式什么像素最清晰
  16. 背景色及色彩搭配方案推荐
  17. 安全体系建设-基础安全
  18. Windows10官网原版系统下载地址汇总
  19. 我叫MT4怎么在电脑上玩?我叫MT4手游安卓模拟器电脑版操作教程
  20. 雨林木风:dll文件下载网站

热门文章

  1. linux安装redis 完整步骤 主从结构 和 cluster 集群搭建
  2. matlab求解微分方程ode23
  3. 怎样恢复误删计算机管理员,win10管理员账号误删只有普通权限怎么恢复
  4. randn函数 python_Python numpy matrix randn()用法及代码示例
  5. python安装requirement.txt的扩展包
  6. mysql 月初 月末_月初 月末 sql 语句(日期所在月的第一天,最后一天)
  7. GetLastError()函数
  8. 梯度的旋度为零证明_旋度的逆运算
  9. hyperledger fabric 2.3.3 环境搭建教程
  10. 《炬丰科技-半导体工艺》化学添加剂对KOH 溶液中Si表面反应性的影响