>

Java8 stream中的groupingBy

一、单字段、多字段分组

复制代码
List<String> items =
        Arrays.asList("apple", "apple", "banana",
                "apple", "orange", "banana", "papaya");

Map<String, Long> result =
        items.stream().collect(
                Collectors.groupingBy(
                        Function.identity(), Collectors.counting()
                )
        );
System.out.println(result);
复制代码

输出如下:

{papaya=1, orange=1, banana=2, apple=3}

  在实际需求中,我们可能需要对一组对象进行分组,而且分组的条件有多个。比如对国家和产品类型进行双重分组,一种比较复杂的方法是先对产品类型进行分组,然后对每一个产品类型中的国家名进行分组求和。示例如下:

复制代码
Map<String, List<item>> countMap = recordItems.stream().collect(Collectors.groupingBy(o -> o.getProductType()));

List<Record> records = new ArrayList<Record>;
countMap.keySet().forEach(productType -> {
    Map<String, Long> countMap1 = countMap.get(productType).stream().collect(Collectors.groupingBy(o -> o.getCountry(), Collectors.counting()));
    countMap1(key).stream().forEach(country -> {
        Record record = new Record();
        record.set("device_type", productType);
        record.set("location", country;
        record.set("count", countMap1(key).intValue());
        records.add(record);
    });
});
复制代码
  上面的方法在应对两个字段的分组要求时,还能应付的过来,但如果字段超过两个时,每增加一个字段,就会多出很多代码行,显然不太合理。更合理的方法是,增加一个 getKey()方法,返回多个字段组成的唯一key,比如通过下划线连接等等。示例如下:
复制代码
// 分组统计
Map<String, Long> countMap = records.stream().collect(Collectors.groupingBy(o -> o.getProductType() + "_" + o.getCountry(), Collectors.counting()));

List<Record> countRecords = countMap.keySet().stream().map(key -> {
    String[] temp = key.split("_");
    String productType = temp[0];
    String country = temp[1];
    
    Record record = new Record();
    record.set("device_type", productType);
    record.set("location", country;
    record.set("count", countMap.get(key).intValue());
    return record;
}).collect(Collectors.toList());
复制代码

二、分组获取最新一条数据再合并成list

这种需求还是挺常见的
List<MemberSolutionVo> list = new ArrayList<>();
...
Map<String, MemberSolutionVo> collect = list.stream().collect(
                    Collectors.groupingBy(MemberSolutionVo::getUuid,
                            Collectors.collectingAndThen(Collectors.reducing((c1, c2) -> c1.getSolutionId().intValue() > c2.getSolutionId().intValue() ? c1 : c2),
                                    Optional::get)));
            list = new ArrayList<>(collect.values());

 

参考文章:

https://www.jianshu.com/p/dd5121c8fa89

https://codeleading.com/article/40836192324

 

posted @   字节悦动  阅读(799)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示

目录导航