在不使用flatMap的情况下实现flatMap效果

时间:2016-10-23 05:44:29

标签: 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) {
            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执行此操作?

3 个答案:

答案 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的重载版本,其中包含参数supplieraccumulatorcombiner

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; });