【问题标题】:Concatenate Collections with Java 8使用 Java 8 连接集合
【发布时间】:2014-05-18 13:34:09
【问题描述】:

我想遍历集合的集合。使用番石榴我会这样做:

import static com.google.collections.Iterables.*;

class Group {
    private Collection<Person> persons;
    public Collection<Person> getPersons();
}

class Person {
    private String name;
    public String getName();
}

Collection<Group> groups = ...;
Iterable<Person> persons = concat(transform(groups, Group::getPersons()));
Iterable<String> names = transform(persons, Person::getName);

但是我怎样才能对 Java 8 流做同样的事情呢?

groups.stream().map(Group::getPersons())...?

【问题讨论】:

    标签: java guava java-8 java-stream


    【解决方案1】:

    我猜你需要flatMap:

    Stream<Person> persons = groups.stream().flatMap(g -> g.getPersons().stream());
    

    【讨论】:

      【解决方案2】:

      您可以通过将流的所有元素平面映射到您的流中来实现这一点。

      让我用这段代码解释一下:

      groups.stream()
              .flatMap(group -> group.getPersons().stream());
      

      你在这里做的是:

      1. 获取Stream&lt;Collection&lt;Group&gt;&gt;
      2. 然后将每个从Group 获得的Stream&lt;Person&gt; 平面映射回您的原始流,该流的类型为Stream&lt;Person&gt;

      现在flatMap()之后,你可以用得到的Stream&lt;Person&gt;做任何你想做的事情。

      【讨论】:

      • 这个评测还会偷懒吗?例如,如果我只想找出第一个人的名字?
      • @PhilippJardas 是的,大多数 Stream&lt;E&gt; 操作是懒惰的。您可以在 javadoc 中找到更多关于哪些不是惰性的,例如 sorted() 不是惰性的。
      • 太好了,谢谢!虽然有几个正确的答案,但我会接受这个,因为它是第一个。 :-)
      • @PhilippJardas JBNizet 和 RohitJain 实际上更快。
      【解决方案3】:
      Stream<Person> persons = groups.stream().flatMap(g -> g.getPersons().stream());
      

      【讨论】:

      • Hmmyep,不是很“优雅”;)我猜某个地方的某个人已经想出了一个Streams.concat()...尽管他们必须小心这些流的.characteristics()
      • 怎么不优雅?这是一个经典的函数式成语,它完全是惰性的。为什么 Streams.concat() 会更优雅?
      • +1 如果您尝试实现concat,您会发现自己以flatMap(x-&gt;x) 结束。在 Clojure 中,我实际上无法决定是 (apply concat ...) 还是 (flatmap identity ...)
      猜你喜欢
      • 2011-07-13
      • 2015-08-03
      • 1970-01-01
      • 2017-08-08
      • 2019-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多