Java 8中的Stream函数分组到值为Map的Map

4

我正在尝试收集列表的结果,并将它们组织成一个值为Map的Map:

private Map<Organisation, Map<LocalDate, Status>> getSummaries(final List<Status> summaries) {
    return summaries
            .stream()
            .collect(groupingBy(Status::getOrganisation,
                    toMap(Status::getProcessedDate, Function.identity())));
}

当列表中不同的值的getProcessedDate()相同时,我会收到java.lang.IllegalStateException: Duplicate key错误。

有没有办法将具有相同processeddate的多个对象合并到地图中?

例如,假设列表中有以下这些对象:

Summary(ProcesseDate=2020-01-30, Organisation=ABC, status=OK, statusCount=5)
Summary(ProcesseDate=2020-01-30, Organisation=ABC, status=FAILED, statusCount=2)
Summary(ProcesseDate=2020-01-30, Organisation=APPLE, status=OK, statusCount=5)
Summary(ProcesseDate=2020-01-30, Organisation=APPLE, status=REJECTED, statusCount=5)

地图中包含的值应该是:

key=ABC
   value { key=2020-01-30, value= Summary(ProcesseDate=2020-01-30, Organisation=ABC, status=OK, statusCount=5), Summary(ProcesseDate=2020-01-30, Organisation=ABC, status=FAILED, statusCount=2) }

当我尝试使用toMap(Status :: getProcessedDate,Function.identity(),(v1,v2) -&gt; v2)));时,它会删除其中一个条目。

将映射的值类型更改为列表,并在此阶段将它们组合起来(v1,v2)-> v1.add(v2); 返回v1; - b.GHILAS
2个回答

4

如果您不想合并数据且没有唯一键,您可能只是在寻找嵌套分组:

private Map<Organisation, Map<LocalDate, List<Status>>> getSummaries(final List<Status> summaries) {
    return summaries
            .stream()
            .collect(groupingBy(Status::getOrganisation, groupingBy(Status::getProcessedDate)));
}

0

如果您想合并键,可以使用Map.merge()

map.merge(key, value, bifunction); 检查 key 是否存在于映射中。如果不存在,则调用 map.put(key, value); 如果存在,则将 bifunction 应用于现有的键和值,并将其存储在映射中。

例如,如果您有一个 Map<String,Integer>,用于计算通过某个段落中的单词出现次数,您可以使用以下代码:

List<String> words = ...
Map<String, Integer> wordCount = ...

words.forEach(s -> wordCount.merge(s, 1, (word, count) -> count + 1));

您可以使用此代码来避免在程序中添加重复的键。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接