使用Java 8流进行复杂聚合
给定一个类项目:
public class Item { private String field1; private String field2; private String field3; private Integer field4; // getters,constructor... } 另一个类Group(field1和field2存储Item中的等效字段): public class Group { private String field1; private String field2; } 我有一个List< Item>我需要聚合到以下结构的地图中: Map<Group,Map<Field3,List<Field4>>> 示例数据: Field1 | Field2 | Field3 | Field4 ------ | ------ | ------ | ------ "f1" | "f2" | "a" | 1 "f1" | "f2" | "a" | 2 "f1" | "f2" | "a" | 3 "f1" | "f2" | "b" | 4 "f1" | "f2" | "b" | 5 "f1" | "f2" | "c" | 6 "f1a" | "f2a" | "a" | 7 "f1a" | "f2a" | "a" | 8 预期结果如下: Group(field1=f1a,field2=f2a)={b=[7,8]},Group(field1=f1,field2=f2)={a=[1,2,3],b=[4,5],c=[6]} 到目前为止,我已经能够通过Field1,Field2和Field3进行聚合,这样我就有了以下结构(其中GroupEx代表一个保存Field1,Field2和Field3的POJO): Map<GroupEx,List<Field4>> 以这种方式聚合的代码是: Map<GroupEx,List<Integer>> aggregated = items.stream() .collect(Collectors.groupingBy(item -> new GroupEx(x.getField1(),x.getField2(),x.getField3()),Collectors.mapping(Item::getField4,Collectors.toList()))); 我正努力让语法正确,允许我按Field1和Field2分组,然后按照我需要的方式将Field3和Field4分组到地图中. “长手”语法是: Map<Group<String,String>,Map<String,List<Integer>>> aggregated = new HashMap<>(); for (Item item : items) { Group key = new Group(item.getField1(),item.getField2()); Map<String,List<Integer>> field3Map = aggregated.get(key); if (field3Map == null) { field3Map = new HashMap<>(); aggregated.put(key,field3Map); } List<Integer> field4s = field3Map.get(item.getField3()); if (field4s == null) { field4s = new ArrayList<>(); field3Map.put(item.getField3(),field4s); } field4s.add(item.getField4()); } 有人能告诉我如何实现目标分组吗? 解决方法
这是
downstream collectors功能的便利之处.
import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.mapping; import static java.util.stream.Collectors.toList; ... List<Item> list = .... Map<Group,List<Integer>>> map = list.stream().collect(groupingBy(i -> new Group(i.getField1(),i.getField2()),groupingBy(Item::getField3,mapping(Item::getField4,toList())))); 首先,按照“组”字段对这些项目进行分组(此时为“地图<组,列表<项目>>”),然后将每个值(列表<项目>)再次映射到地图中,按字段3进行分组( Map< Group,Map< Field3,List< Item>>). 然后,您将第二个地图中的值映射到field4,然后将它们收集到一个列表中,最后得到一个Map< Group,List< Field4>>. 根据您的输入,它输出: {Group{field1='f1a',field2='f2a'}={a=[7,Group{field1='f1',field2='f2'}={a=[1,c=[6]}} (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |