<导航

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 @ 2022-11-24 00:56  字节悦动  阅读(982)  评论(0)    收藏  举报