学习了groupingBy的用法,里面经常会用到 Collectors.collectingAndThen,我理解为后续操作。

JDK源码

java.util.stream.Collectors#collectingAndThen方法的作用是将Collector的结果在执行一个额外的finisher转换操作,其源码如下:

/*** Adapts a {@code Collector} to perform an additional finishing* transformation.  For example, one could adapt the {@link #toList()}* collector to always produce an immutable list with:* <pre>{@code*     List<String> people*         = people.stream().collect(collectingAndThen(toList(), Collections::unmodifiableList));* }</pre>** @param <T> the type of the input elements* @param <A> intermediate accumulation type of the downstream collector* @param <R> result type of the downstream collector* @param <RR> result type of the resulting collector* @param downstream a collector* @param finisher a function to be applied to the final result of the downstream collector* @return a collector which performs the action of the downstream collector,* followed by an additional finishing step*/
public static<T, A, R, RR> Collector<T, A, RR> collectingAndThen(Collector<T, A, R> downstream, Function<R, RR> finisher) {Set<Collector.Characteristics> characteristics = downstream.characteristics();if (characteristics.contains(Collector.Characteristics.IDENTITY_FINISH)) {if (characteristics.size() == 1) {characteristics = Collectors.CH_NOID;} else {characteristics = EnumSet.copyOf(characteristics);characteristics.remove(Collector.Characteristics.IDENTITY_FINISH);characteristics = Collections.unmodifiableSet(characteristics);}}return new CollectorImpl<>(downstream.supplier(),downstream.accumulator(),downstream.combiner(),downstream.finisher().andThen(finisher),characteristics);
}

T:输入元素的类型
A:下游Collector的中间堆积类型
R:下游Collector的结果类型
RR:结果Collector的结果类型
参数:此方法接受下面列出的两个参数

downstream: Collector的一个实例,可以使用任何Collector
finisher: 类型是Function,该函数将应用于下游Collector的最终结果
返回值:返回一个执行下游Collector动作的Collector,然后在finisher函数的帮助下执行附加的转换步骤。

使用:

模拟数据:

 public static JSONArray initData(){String data = "[{\"code\":\"4\",\"codeType\":\"ALRAM\",\"sortId\":\"4\",\"name\":\"特级告警\"},{\"code\":\"2\",\"codeType\":\"ALRAM\",\"sortId\":\"2\",\"name\":\"中级告警\"},{\"code\":\"3\",\"codeType\":\"ALRAM\",\"sortId\":\"3\",\"name\":\"严重告警\"},{\"code\":\"1\",\"codeType\":\"ALRAM\",\"sortId\":\"1\",\"name\":\"普通告警\"},{\"code\":\"2\",\"codeType\":\"NOTICE\",\"sortId\":\"2\",\"name\":\"邮箱通知\"},{\"code\":\"1\",\"codeType\":\"NOTICE\",\"sortId\":\"1\",\"name\":\"短信通知\"},{\"code\":\"3\",\"codeType\":\"NOTICE\",\"sortId\":\"3\",\"name\":\"微信消息通知\"}]";return JSON.parseArray(data);}

toList

获取字段类型的各名称

  public static void main(String[] args){JSONArray items = initData();Map<String, List<String>> codeTypeNameMap1 = ListUtils.emptyIfNull(items).stream().map(e -> (JSONObject) e).collect(Collectors.groupingBy(e -> MapUtils.getString(e, "codeType"), Collectors.collectingAndThen(Collectors.toList(),t -> ListUtils.emptyIfNull(t).stream().map(x -> MapUtils.getString(x, "name")).filter(Objects::nonNull).distinct().collect(Collectors.toList()))));System.out.println(JSON.toJSONString(codeTypeNameMap1));}

结果:

{"NOTICE": ["邮箱通知", "短信通知", "微信消息通知"],"ALRAM": ["特级告警", "中级告警", "严重告警", "普通告警"]
}

不过这种写法会有点繁琐,使用mapping更为简便直观:

Map<String, List<String>> codeTypeNameMap2 = ListUtils.emptyIfNull(items).stream().map(e -> (JSONObject) e)
.collect(Collectors.groupingBy(e -> MapUtils.getString(e, "codeType"),
Collectors.mapping(f1 -> MapUtils.getString(f1, "name"), Collectors.toList())));System.out.println(JSON.toJSONString(codeTypeNameMap2));

toMap

获取字段类型的字典及其名称

 public static void main(String[] args){JSONArray items = initData();Map<String, Map<String, String>> codeTypeMap1 = ListUtils.emptyIfNull(items).stream().map(e -> (JSONObject) e)
.collect(Collectors.groupingBy(e -> MapUtils.getString(e, "codeType"),
Collectors.collectingAndThen(Collectors.toMap(f1 -> MapUtils.getString(f1, "code"),f2 -> MapUtils.getString(f2, "name"), (x, y) -> x), v -> v)));System.out.println(JSON.toJSONString(codeTypeMap1));}

结果:

{"NOTICE": {"1": "短信通知","2": "邮箱通知","3": "微信消息通知"},"ALRAM": {"1": "普通告警","2": "中级告警","3": "严重告警","4": "特级告警"}
}

这个直接用toMap的方式也更为简便直观

Map<String, Map<String, String>> codeTypeMap2 = ListUtils.emptyIfNull(items).stream().map(e -> (JSONObject) e).collect(Collectors.groupingBy(e -> MapUtils.getString(e, "codeType"),Collectors.toMap(f1 -> MapUtils.getString(f1, "code"),f2 -> MapUtils.getString(f2, "name"), (x, y) -> x)));System.out.println(JSON.toJSONString(codeTypeMap2));

maxBy

分组后找到code最大的内容

public static void main(String[] args){JSONArray items = initData();Map<String, JSONObject> codeMax = ListUtils.emptyIfNull(items).stream().map(e -> (JSONObject) e).collect(Collectors.groupingBy(e -> MapUtils.getString(e, "codeType"),Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingInt(f1 -> MapUtils.getInteger(f1, "code"))), Optional::get)));System.out.println(JSON.toJSONString(codeMax));}

结果:

{"NOTICE": {"code": "3","codeType": "NOTICE","sortId": "3","name": "微信消息通知"},"ALRAM": {"code": "4","codeType": "ALRAM","sortId": "4","name": "特级告警"}
}

这个可以直接用toMap和BinaryOperator.maxBy进行处理

public static void main(String[] args){JSONArray items = initData();Map<String, JSONObject> codeMax = ListUtils.emptyIfNull(items).stream().map(e -> (JSONObject) e).collect(Collectors.toMap(e -> MapUtils.getString(e, "codeType"),Function.identity(),
BinaryOperator.maxBy(Comparator.comparingInt(f1 -> MapUtils.getInteger(f1, "code")))));System.out.println(JSON.toJSONString(codeMax));}

sort asc

分组后,根据sortId进行排序-正序

 public static void main(String[] args){JSONArray items = initData();Map<String, List<JSONObject>> groupAscSort = ListUtils.emptyIfNull(items).stream().map(e -> (JSONObject) e).collect(Collectors.groupingBy(e -> MapUtils.getString(e, "codeType"),LinkedHashMap::new,Collectors.collectingAndThen(Collectors.toList(), s ->s.stream().sorted(Comparator.comparing(e -> e.getInteger("sortId"))).collect(Collectors.toList()))));System.out.println(JSON.toJSONString(groupAscSort));}

结果:

{"ALRAM": [{"code": "1","codeType": "ALRAM","sortId": "1","name": "普通告警"}, {"code": "2","codeType": "ALRAM","sortId": "2","name": "中级告警"}, {"code": "3","codeType": "ALRAM","sortId": "3","name": "严重告警"}, {"code": "4","codeType": "ALRAM","sortId": "4","name": "特级告警"}],"NOTICE": [{"code": "1","codeType": "NOTICE","sortId": "1","name": "短信通知"}, {"code": "2","codeType": "NOTICE","sortId": "2","name": "邮箱通知"}, {"code": "3","codeType": "NOTICE","sortId": "3","name": "微信消息通知"}]
}

sort desc

分组后,根据sortId进行排序-反序

public static void main(String[] args){JSONArray items = initData();Map<String, List<JSONObject>> groupReverseSort = ListUtils.emptyIfNull(items).stream().map(e -> (JSONObject) e).collect(Collectors.groupingBy(e -> MapUtils.getString(e, "codeType"),LinkedHashMap::new,Collectors.collectingAndThen(Collectors.toList(), s ->s.stream().sorted((c1, c2) ->MapUtils.getInteger(c2, "sortId").compareTo(MapUtils.getInteger(c1, "sortId"))).collect(Collectors.toList()))));System.out.println(JSON.toJSONString(groupReverseSort));}

结果:

{"ALRAM": [{"code": "4","codeType": "ALRAM","sortId": "4","name": "特级告警"}, {"code": "3","codeType": "ALRAM","sortId": "3","name": "严重告警"}, {"code": "2","codeType": "ALRAM","sortId": "2","name": "中级告警"}, {"code": "1","codeType": "ALRAM","sortId": "1","name": "普通告警"}],"NOTICE": [{"code": "3","codeType": "NOTICE","sortId": "3","name": "微信消息通知"}, {"code": "2","codeType": "NOTICE","sortId": "2","name": "邮箱通知"}, {"code": "1","codeType": "NOTICE","sortId": "1","name": "短信通知"}]
}

总结:

Collectors.collectingAndThen除了排序的,另外其它都直接替换。但是也要熟悉,这样当遇到需要进一步处理数据,也不知道有更简便的方法的时候,就可以直接用 collectingAndThen的方式去写。再不行,就分两步写。

java8 Collectors.collectingAndThen 常用用法相关推荐

  1. java8 stream().map().collect()用法

    java8 stream().map().collect()用法 有一个集合: List<User> users = getList(); //从数据库查询的用户集合 现在想获取User的 ...

  2. list的stream流常用用法

    1.list的stream流常用用法 代码功能示例类型如下: 1.过滤 2.bigdecimal求和 3.字符串拼接 4.取出list的某个字段 5.list集合依据某个字段进行正序 6.list集合 ...

  3. java8 collectors类_java8之collectors

    java8中提供了对集合进行转化,然后进行归集的的操作.这就不得不提Collectors这个类了,真的很强大,我们看示例吧. KeyAndValue a1 = newKeyAndValue().set ...

  4. 【Android 异步操作】Handler 机制 ( Handler 常用用法 | HandlerThread 简介 | HandlerThread 源码注释分析 )

    文章目录 一.Handler 常用用法 二.HandlerThread 简介 三.HandlerThread 源码 一.Handler 常用用法 主线程 Handler 主要作用 : Looper 和 ...

  5. 【Android 异步操作】Timer 定时器 ( Timer 与 TimerTask 基本使用 | Timer 定时器常用用法 | Timer 源码分析 )

    文章目录 一.Timer 定时器基本使用 二.Timer 定时器常用用法 三.Timer 源码分析 四.Timer 部分源码注释 五.源码及资源下载 参考文档 : Timer 定时器 API 文档 T ...

  6. 【Kotlin】Kotlin enum 枚举类 ( 常用用法 | 初始化成员变量 | 实现抽象方法 | 实现接口 | 获取名称和位置索引 | 调用枚举常量方法 )

    文章目录 I . 枚举类常用用法 II . 枚举类初始化 III. 枚举类匿名类 IV . 枚举类实现接口 V . 获取枚举常量名称和位置索引 VI . 获取枚举常量的成员变量 VII . 调用枚举常 ...

  7. Python中的基本函数及其常用用法简析

    分享Python中的基本函数及其常用用法简析,首先关于函数的解释函数是为了达到某种目的而采取的行为,函数是可重复使用的,用来实现某个单一功能或者功能片段的代码块,简单来说就是由一系列的程序语句组成的程 ...

  8. 【Data Mining】机器学习三剑客之Numpy常用用法总结

    点击"小詹学Python",选择"置顶"公众号 重磅干货,第一时间送达 本文转载自AI蜗牛车,禁二次转载 一.前言 玩数据分析.数据挖掘.AI的都知道这个pyt ...

  9. grep参数说明及常用用法

    grep参数说明及常用用法 查看文件内容 [kou@localhost ~]$ more size.txt b124230 b034325 a081016 m7187998 m7282064 a022 ...

最新文章

  1. Spring+SpringMVC+MyBatis深入学习及搭建(十七)——SpringMVC拦截器
  2. release,debug库互调用,32位,64位程序与库互调用
  3. 【CodeForces - 227C】Flying Saucer Segments (思维)
  4. 设备驱动,字符设备驱动、(总线)设备驱动模型、sysfs文件系统、平台设备驱动
  5. eclipse定义和修改模板
  6. 2020年十大消费新机遇
  7. 在后台获取前台按钮里的值(如LinkButton)
  8. Spring框架----Spring的环绕通知
  9. 使用vue的生命周期函数_异步_同步获取字典数据---基于Vue的uniapp手机端_前端UI_uview工作笔记003
  10. VC中将bmp作为资源文件写入EXE或DLL,然后内部调用(转)
  11. (Deep learning)深度卷积网络实战——第二部分
  12. php _get invalid,PHP 错误: ZipArchive::getFromName(): Invalid or unitialized Zip object in 解决方法...
  13. apan在PHP什么意思,Apanteles是什么意思
  14. FPGA | Vivado 查看最大工作频率(Fmax)
  15. kalilinux生成安卓木马(仅供学习使用)
  16. (转发)线性代数的本质
  17. DNS总是出现问题怎么办?
  18. QQ在线图标 离线 QQ开通在线QQ服务 QQ陌生人直接聊天
  19. Endnote 软件中的名词解释
  20. 连续变量离散化类别变量

热门文章

  1. 2022年施工升降机司机(建筑特殊工种)考试试题及在线模拟考试
  2. Python+Selenium定位到多个相同的元素取指定的那一个
  3. jsp源码审计的积累
  4. 跨境电商的命运路口:产品出海还是品牌出海?
  5. C# log4net 日志输出超详细
  6. 简单两步自己动手制作联想windows7 sp1 64位旗舰版安装镜像文件windows7旗舰版主...
  7. 智能电视关机后需不需要拔插头或关闭电源?
  8. 达人评测 2022款联想ThinkPad T16和T14区别是什么,哪个好
  9. 字体如何随着页面缩小而变化
  10. php require的用法,php require用法详解