java8 stream groupby后的数据结构是否可以重构

result = list.stream().collect(Collectors.groupingBy(q -> q.getBrand()));

这样分组后,得到的数据结构,key是分组的组名,
我想要的是可以重构这个分组后的数据结构,用myKey:key,myValue:当前组对应的分组的数据

应该怎么一句话写完?因为我现在没办法,只能再写一个循环,来构造这个结构。

阅读 15.8k
3 个回答

你采用的是groupingBy一个参数的方法,该方法只能传参一个Function作为Key的映射函数

但是其实Collectors.groupingBy最多是有三个参数的方法的,其他两个参数的还有一个参数的都是三个参数的方法的重载而已,所以你要达到处理分组后的Value数据,就需要了解根本上三个参数的方法到底提供了哪些能力

Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,
                                  Supplier<M> mapFactory,
                                  Collector<? super T, A, D> downstream) {

可以看到有三个参数,第一个参数就是key的Function了,第二个参数是一个map工厂,也就是最终结果的容器,一般默认的是采用的HashMap::new,最后一个参数很重要是一个downstream,类型是Collector,也是一个收集器,那就是说,这三个参数其实就是为了解决分组问题的

  1. 第一个参数:分组按照什么分类

  2. 第二个参数:分组最后用什么容器保存返回

  3. 第三个参数:按照第一个参数分类后,对应的分类的结果如何收集

综上所诉,你需要对第三个参数进行传参就可以达到你要的目的了
由于之前说到的,第二个参数默认是HashMap::new,所以你就可以采用Collectors.groupingBy两个参数的方法,如下可以看到,第二个参数是HashMap::new

public static <T, K, A, D>
    Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
                                          Collector<? super T, A, D> downstream) {
        return groupingBy(classifier, HashMap::new, downstream);
    }

其实一个参数的Collectors.groupingBy方法的第三个参数收集器其实默认是Collectors.toList,所以你上面写的返回最终的类型是Map<String, List>

因为不知道你那个集合数据类型,所以不好根据你的来举例,我可以写一些我的小例子

Student
String type
int score
String name

List<Student> students = new ArrayList<>()

// 每个学生类型的总分数
Map<String, Integer> map1 = 
students.stream.collect(Collectors.groupingBy(Student::getType, Collectors.summingInt(Student::getScore))));

// 每个学生类型中的得分最高的那个学生
Map<String, Optional<Student>> map2 = students.stream.collect(Collectors.groupingBy(Student::getType, Collectors.maxBy(Comparator.comparing(Student::getScore))));

反正第三个参数收集器你还可以根据Collectors里找到很多,实在不行可以自定义收集器的,希望能帮到你

朋友, 我也遇到这个问题, 没找到太好的办法, 最后也是循环groupBy后的map,得到我想要的数据结构.

我提供一个写法, 本质还是还是循环map,只不过语句能短一点.如果你有好写法了麻烦告诉我

List<Map> map = resultList.stream()
    .collect(groupingBy(SwIndustryDto::getChart,TreeMap::new, Collectors.mapping(SwIndustryDto::getFcode, Collectors.toList()))) 
        .entrySet().stream().map(e->{  
          Map item = new HashMap();  
          item.put("nKey",e.getKey());  
          item.put("nValue",e.getValue());  
         return item;  
}).collect(Collectors.toList());

https://stackoverflow.com/que...

Map<String, List<Map<String, String>>> maplist = dclist.stream()  
        .collect(Collectors.groupingBy(map -> map.get("name"),  
                Collectors.mapping(map -> {  
                    Map<String, String> temp = new HashMap<String, String>(map);  
                    temp.remove("name");  
                    return temp;  
                }, Collectors.toList())));  
  
List<Map<String, Object>> res = new ArrayList<>();  
for (String key : maplist.keySet()) {  
    res.add(Map.of("name", key, "dclist", maplist.get(key)));  
}

原格式

[
  {
    "dc": 0.100,
    "date": "202003-1",
    "name": "测试1"
  },
  {
    "dc": 0.100,
    "name": "测试1",
    "date": "202003-2"
  },
  {
    "dc": 0.100,
    "name": "测试1",
    "date": "202003-4"
  },
  {
    "name": "测试1",
    "dc": 1.000,
    "date": "202003-3"
  },
  {
    "date": "202003-3",
    "dc": 0.300,
    "name": "测试2"
  },
  {
    "date": "202003-1",
    "name": "测试2",
    "dc": 0.400
  },
  {
    "date": "202003-2",
    "name": "测试2",
    "dc": 0.400
  },
  {
    "dc": 0.500,
    "date": "202003-5",
    "name": "测试2"
  }
]

转化后格式

[
  {
    "name": "测试2",
    "values": [
      {
        "date": "202003-3",
        "dc": 0.300
      },
      {
        "date": "202003-1",
        "dc": 0.400
      },
      {
        "date": "202003-2",
        "dc": 0.400
      },
      {
        "date": "202003-5",
        "dc": 0.500
      }
    ]
  },
  {
    "name": "测试1",
    "values": [
      {
        "date": "202003-1",
        "dc": 0.100
      },
      {
        "date": "202003-2",
        "dc": 0.100
      },
      {
        "date": "202003-4",
        "dc": 0.100
      },
      {
        "date": "202003-3",
        "dc": 1.000
      }
    ]
  }
]
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏