Java 无需使用flatMap即可实现flatMap效果
我有一个定义开发人员的类Java 无需使用flatMap即可实现flatMap效果,java,java-stream,Java,Java Stream,我有一个定义开发人员的类 class Developer { private final String name; Set<String> skills = new HashSet<>(); public Developer(final String name, final String... skills) { this.name = name; for (final String skill : skills)
class Developer {
private final String name;
Set<String> skills = new HashSet<>();
public Developer(final String name, final String... skills) {
this.name = name;
for (final String skill : skills) {
this.skills.add(skill);
}
}
}
有没有办法通过
流
s而不使用平面图
?您可以使用重载版本的收集器。collect
接受参数供应商
,累加器
和组合器
Set<String> skills = developers.stream().map(Developer::getSkills)
.collect(HashSet::new, Set::addAll, Set::addAll);
System.out.println("Skills :: " + skills);
编辑
不需要在收集器内部使用线程安全结构,因为它表示:
当并行执行时,可以实例化、填充和合并多个中间结果,以保持可变数据结构的隔离。因此,即使在与非线程安全的数据结构(如ArrayList)并行执行时,并行缩减也不需要额外的同步
flatMap
是一条路要走。很高兴知道你的问题背后的动机
实现相同结果的另一种方法是使用(如其他答案所述)。
您还可以避免使用映射
,将所有内容放入收集器,如:
Set<String> skills = developers.stream()
.collect(
HashSet<String>::new,
(acum, dev) -> acum.addAll(dev.skills),
Set::addAll
);
Set skills=developers.stream()
.收集(
HashSet::新,
(acum,dev)->acum.addAll(dev.skills),
集合::addAll
);
您可以这样使用reduce
Set<String> set = people.stream()
.map(d -> d.skills)
.reduce(new HashSet<String>(),
(map, list) -> { map.addAll(list); return map; });
Set=people.stream()
.map(d->d.skills)
.reduce(新的HashSet(),
(映射,列表)->{map.addAll(列表);返回映射;});
为什么不使用flatMap
?这是正确的方法。@JohnKugelman我只是想更好地理解map和flatMap之间的区别,我想这个问题的答案会帮助我更好地理解。@John我没有保持任何状态,为什么不安全?你能解释一下我需要使用并发收集吗?因为好的捕获,所以不需要线程安全的结构!我用一个ConcurrentSkipListSet
@JohnKugelman修改了mi解决方案。请查看我的编辑。这里不需要线程安全的结构。而且,它会为集合中的每个项目生成一个新的HashSet
。我不介意在haskell上这样做,但在java上应该考虑到这一点。@Logaln在本期中,并行化没有任何优势。
Set<String> skills = developers.stream()
.collect(
HashSet<String>::new,
(acum, dev) -> acum.addAll(dev.skills),
Set::addAll
);
Set<String> set = people.stream()
.map(d -> d.skills)
.reduce(new HashSet<String>(),
(map, list) -> { map.addAll(list); return map; });