使用Java8流的复杂聚合

使用Java8流的复杂聚合,java,java-8,java-stream,Java,Java 8,Java Stream,给定一个类项目: public class Item { private String field1; private String field2; private String field3; private Integer field4; // getters, constructor... } 和另一个类组(field1和field2存储项中的等效字段): 我有一个列表,我需要将其聚合成以下结构的映射: Map<Group, Map<

给定一个类项目:

public class Item {
    private String field1;
    private String field2;
    private String field3;
    private Integer field4;

    // getters, constructor...
}
和另一个类组(field1和field2存储项中的等效字段):

我有一个
列表
,我需要将其聚合成以下结构的映射:

Map<Group, Map<Field3, List<Field4>>>
预期结果如下所示:

Group(field1=f1a, field2=f2a)={b=[7, 8]}, Group(field1=f1, field2=f2)={a=[1, 2, 3], b=[4, 5], c=[6]}
到目前为止,我已经能够按字段1、字段2和字段3进行聚合,因此我有以下结构(其中
GroupEx
表示包含字段1、字段2和字段3的POJO):

Map
以这种方式聚合的代码是:

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())));
Map aggregated=items.stream()
.collect(Collectors.groupingBy(item->newgroupex(x.getField1()、x.getField2()、x.getField3())
,Collectors.mapping(Item::getField4,Collectors.toList());
我正在努力获得正确的语法,以允许我按字段1和字段2分组,然后按字段3和字段4分组,以我需要的方式生成一个地图

“long hand”语法是:

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());
}
Map aggregated=newhashmap();
用于(项目:项目){
组键=新组(item.getField1(),item.getField2());
Map field3Map=aggregated.get(键);
if(field3Map==null){
field3Map=新的HashMap();
聚合。放置(键,字段3map);
}
List field4s=field3Map.get(item.getField3());
if(field4s==null){
field4s=新的ArrayList();
field3Map.put(item.getField3(),field4s);
}
field4s.add(item.getField4());
}
有人能告诉我如何实现目标分组吗?

这就是该功能的用武之地

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, Map<String, List<Integer>>> map =
    list.stream().collect(groupingBy(i -> new Group(i.getField1(), i.getField2()),
                                     groupingBy(Item::getField3, mapping(Item::getField4, toList()))));

您还重写了
等于
哈希代码
对吗?为了在为
映射创建键时比较两个组
@andreim Yes,否则由项目生成的每个
都将是映射中唯一的键感谢Alexis-这正是我所需要的。令人恼火的是,我已经非常接近了,但是被最后的
映射
调用绊倒了,编译器也没有给我多少帮助。
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())));
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());
}
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, Map<String, List<Integer>>> map =
    list.stream().collect(groupingBy(i -> new Group(i.getField1(), i.getField2()),
                                     groupingBy(Item::getField3, mapping(Item::getField4, toList()))));
{Group{field1='f1a', field2='f2a'}={a=[7, 8]}, Group{field1='f1', field2='f2'}={a=[1, 2, 3], b=[4, 5], c=[6]}}