如何根据class的属性收集对象到List,然后Map到java8或11中的HashMap?

How to collect objects to List based on properties of the class and then Map to HashMap in java 8 or 11?

我有类类似于:

class Response {
    Source source;
    Target target;
}

class Source {
    Long sourceId;
    String sourceName;
}

class Target {
    Long targetId;
    String targetName;
}

Response, source(sourceId,sourceName)中对于不同的目标对象可能是相同的。

我在 Response 中输入了这 4 个属性 sourceId, sourceName, targetId, targetName。我可以在多行上使用相同的 sourceIdsourceName,但 targetIdtargetName 将始终不同。

我想将所有目标对象分组到源相同的List

我有 List 个 Response 对象,我正在尝试对其执行 stream() 操作,例如:

Map<Source, List<Target>> res = results
        .stream()
        .collect(Collectors.groupingBy(
            Response::getSource)
        //collect to map

所以我的最终输出 JSON 看起来像:

"Response": { 
    "Source":       {  
        "sourceId":       "100",   
        "sourceName":      "source1",    
    }
    "Target": [{//grouping target objects with same source
        "targetId":       "10",   
        "targetName":      "target1",   
    }, {
        "targetId":       "20",   
        "targetName":      "target2",   
    }]
}

我假设 sourceName 是字符串(由于 json)

一定要是流吗?

它可能很容易像下面这样完成:

Map<Source,List<Target>> res= new HashMap<>();
for(Response response : results){
        List<Target> sourceTarget = res.computeIfAbsent(response.source, list -> new ArrayList<>());
        sourceTarget.add(response.target);
    }

Class Source 需要正确覆盖 hashCodeequals 方法才能用作 Map 中的键。

但是,应该实现另一个 POJO 以包含所需的输出:

@AllArgsConstructor
class Grouped {
    @JsonProperty("Source")
    Source source;

    @JsonProperty("Target")
    List<Target> target;
}

然后响应列表可以转换如下:

List<Response> responses; // set up the input list

List<Grouped> grouped = responses.stream()
    .collect(Collectors.groupingBy(
        Response::getSource,
        Collectors.mapping(Response::getTarget, Collectors.toList())
    )) // Map<Source, List<Target>> is built
    .entrySet()
    .stream() // Stream<Map.Entry<Source, List<Target>>>
    .map(e -> new Grouped(e.getKey(), e.getValue()))
    .collect(Collectors.toList());