Java Stream Collectors.toMap的值是一个Set。

14

我想使用Java Stream来遍历一个POJO的列表,例如下面的列表List<A>,并将其转换为一个Map Map<String, Set<String>>

例如,类A如下:

class A {
    public String name;
    public String property;
}

我编写了下面的代码,将值收集到一个Map<String, String>中:

final List<A> as = new ArrayList<>();
// the list as is populated ...

// works if there are no duplicates for name
final Map<String, String> m = as.stream().collect(Collectors.toMap(x -> x.name, x -> x.property));

然而,由于可能存在多个具有相同 name 的 POJO,我希望该映射的值为一个 Set。所有具有相同键 nameproperty 字符串都应该放在同一个集合中。

如何实现?

// how do i create a stream such that all properties of the same name get into a set under the key name
final Map<String, Set<String>> m = ???
4个回答

29

groupingBy 正好可以满足您的需求:

import static java.util.stream.Collectors.*;
...
as.stream().collect(groupingBy((x) -> x.name, mapping((x) -> x.property, toSet())));

3
小修正,我认为应该是 import static java.util.stream.Collectors.*; - tkja
2
单个 lambda 参数不需要括号。 - shmosel
代码风格很糟糕,但是正确。 - Sim0rn

7

@Nevay的回答绝对是正确的方法,使用groupingBy,但也可以通过toMap实现,只需将mergeFunction作为第三个参数添加:

as.stream().collect(Collectors.toMap(x -> x.name, 
    x -> new HashSet<>(Arrays.asList(x.property)), 
    (x,y)->{x.addAll(y);return x;} ));

该代码将数组映射到一个Map中,其中键为x.name,值为HashSet,其一个值为x.property。当存在重复的键/值时,会调用第三个参数合并函数来合并两个HashSet
PS. 如果使用Apache Common库,则还可以使用它们的SetUtils::union作为合并器。

3

同工不同酬

Map<String, Set<String>> m = new HashMap<>();

as.forEach(a -> {
    m.computeIfAbsent(a.name, v -> new HashSet<>())
            .add(a.property);
    });

欢迎来到Stackoverflow,如果您希望您的答案被认为是有价值和有帮助的,并获得良好的反馈,请尽量详细地描述问题。 - MohammadReza Alagheband

0
此外,您还可以使用Collectors.toMap函数的合并功能选项 Collectors.toMap(keyMapper,valueMapper,mergeFunction),如下所示:
final Map<String, String> m = as.stream()
                                .collect(Collectors.toMap(
                                          x -> x.name, 
                                          x -> x.property,
                                          (property1, property2) -> property1+";"+property2);

问题是关于收集值到Set<String>而不是String的。 - splatch

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