Java Stream Collectors.toMap值是一个Set

tkj*_*kja 11 java java-8 java-stream

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

例如,A类是:

class A {
    public String name;
    public String property;
}
Run Code Online (Sandbox Code Playgroud)

我编写了下面的代码,将值收集到地图中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));
Run Code Online (Sandbox Code Playgroud)

但是,因为可能有多个相同的POJO name,我希望地图的值为a Set.property同一个键的所有字符串name都应该放在同一个字符集中.

如何才能做到这一点?

// 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 = ???
Run Code Online (Sandbox Code Playgroud)

Nev*_*vay 22

groupingBy完全符合你的要求:

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

  • 小修正,我认为应该是导入静态java.util.stream.Collectors.*; (2认同)
  • 单个 lambda 参数不需要括号。 (2认同)

tex*_*uce 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;} ));
Run Code Online (Sandbox Code Playgroud)

此代码将数组映射到一个 Map,其中键为 as x.name,值为 as,HashSet其中一个值为x.property。当存在重复的key/value时,则调用第三个参数合并函数来合并两个HashSet。

附言。如果你使用Apache Common库,你也可以使用它们SetUtils::union作为合并