Java Stream Collectors.toMap值是一个Set
我想使用Java Stream来运行POJO列表,例如下面的列表List
,并将其转换为Map Map<String, Set>
。
例如,A类是:
class A { public String name; public String property; }
我编写了下面的代码,将值收集到地图Map
:
final List as = new ArrayList(); // the list as is populated ... // works if there are no duplicates for name final Map m = as.stream().collect(Collectors.toMap(x -> x.name, x -> x.property));
但是,因为可能有多个具有相同name
POJO,所以我希望map的值为Set
。 同一个键name
所有property
字符串应该进入同一个集合。
如何才能做到这一点?
// 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> m = ???
groupingBy完全符合你的要求:
import static java.util.stream.Collectors.*; ... as.stream().collect(groupingBy((x) -> x.name, mapping((x) -> x.property, toSet())));
@Nevay的回答绝对是使用groupingBy
的正确方法,但是也可以通过添加mergeFunction作为第三个参数来实现toMap
:
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
用作合并
此外,您可以使用Collectors.toMap函数Collectors.toMap(keyMapper,valueMapper,mergeFunction)的merger函数选项,如下所示:
final Map m = as.stream() .collect(Collectors.toMap( x -> x.name, x -> x.property, (property1, property2) -> property1+";"+property2);
相识又有差别
Map> m = new HashMap<>(); as.forEach(a -> { m.computeIfAbsent(a.name, v -> new HashSet<>()) .add(a.property); });