你可以使用
Collector
中的
of
静态工厂方法来实现这一点:
Map<String, Set<Person>> groupBy = persons.parallelStream()
.collect(Collector.of(
ConcurrentHashMap::new,
( map, person ) -> {
map.computeIfAbsent(person.name, k -> new HashSet<>()).add(person);
map.computeIfAbsent(person.uid, k -> new HashSet<>()).add(person);
map.computeIfAbsent(person.phone, k -> new HashSet<>()).add(person);
},
( a, b ) -> {
b.forEach(( key, set ) -> a.computeIfAbsent(key, k -> new HashSet<>()).addAll(set));
return a;
}
));
如评论中的Holger所建议,以下方法可能优于上述方法:
Map<String, Set<Person>> groupBy = persons.parallelStream()
.collect(HashMap::new, (m, p) -> {
m.computeIfAbsent(p.name, k -> new HashSet<>()).add(p);
m.computeIfAbsent(p.uid, k -> new HashSet<>()).add(p);
m.computeIfAbsent(p.phone, k -> new HashSet<>()).add(p);
}, (a, b) -> b.forEach((key, set) -> {
a.computeIfAbsent(key, k -> new HashSet<>()).addAll(set));
});
它使用了重载的
collect
方法,其作用与我上面建议的语句完全相同。
ConcurrentHashMap
,普通的HashMap
就可以。只有在指定了CONCURRENT
特性时才需要使用ConcurrentHashMap
。顺便说一下,你可以通过使用collect
的三个参数版本来进一步简化解决方案:persons.parallelStream() .collect(HashMap::new, (m, p) -> { m.computeIfAbsent(p.name, k -> new HashSet<>()).add(p); m.computeIfAbsent(p.uid, k -> new HashSet<>()).add(p); m.computeIfAbsent(p.phone, k -> new HashSet<>()).add(p); }, (a, b) -> b.forEach((key, set) -> a.computeIfAbsent(key, k -> new HashSet<>()).addAll(set)));
- HolgerCONCURRENT
特性的Collector
仍然可以与并行流一起使用。在这种情况下,Stream实现会负责适当地使用函数;这就是为什么它可以与任意集合和映射一起使用,而不需要ConcurrentHashMap
。请参见此问答以了解差异的讨论。 - Holger