我有这个定义开发人员的类。
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);
}
}
}
我正在创建开发人员列表。
List<Developer> developers = new ArrayList<>();
people.add(new Developer("Bill", "Javascript", "HTML", "CSS"));
people.add(new Developer("Bob", "Java", "OOP", "Agile"));
people.add(new Developer("Barry", "Data Mining", "Machine Learning", "R"));
现在我想提取一套集体技能。我使用flatMap
这样做:
Set<String> skills = developers.stream().flatMap(dev -> dev.skills.stream()).collect(Collectors.toSet());
有没有办法在不使用Stream
的情况下通过flatMap
执行此操作?
答案 0 :(得分:6)
由于the documentation表示:
,因此无需在收集器内部使用线程安全结构当并行执行时,可以实例化,填充和合并多个中间结果,以便保持可变数据结构的隔离。因此,即使与非线程安全的数据结构(例如ArrayList)并行执行,并行还原也不需要额外的同步。
flatMap
是要走的路。知道你问题背后的动机会很高兴。
实现相同结果的另一种方法是使用collectors(如其他答案所述)。
您也可以避免map
并将所有内容放入收集器中:
Set<String> skills = developers.stream()
.collect(
HashSet<String>::new,
(acum, dev) -> acum.addAll(dev.skills),
Set::addAll
);
答案 1 :(得分:4)
您可以使用Collectors.collect
的重载版本,其中包含参数supplier
,accumulator
和combiner
Set<String> skills = developers.stream().map(Developer::getSkills)
.collect(HashSet::new, Set::addAll, Set::addAll);
System.out.println("Skills :: " + skills);
输出
Skills :: [Java, OOP, CSS, R, Javascript, Agile, Data Mining, HTML, Machine Learning]
答案 2 :(得分:2)
您可以像这样使用reduce
。
Set<String> set = people.stream()
.map(d -> d.skills)
.reduce(new HashSet<String>(),
(map, list) -> { map.addAll(list); return map; });