Java 8 Streams - 使用流将相同类型的多个对象映射到列表

bal*_*_21 4 java collections lambda java-8 java-stream

是否有可能以更好的方式使用流来执行下面提到的步骤?

Set<Long> memberIds = new HashSet<>();
marksDistribution.parallelStream().forEach(marksDistribution -> {
        memberIds.add(marksDistribution.getStudentId());
        memberIds.add(marksDistribution.getTeacherId());
      });
Run Code Online (Sandbox Code Playgroud)

instanceDistribution.getStudentId()并且instanceDistribution.getTeacherId()都是类型Long.

有可能会提出这类问题,但我无法理解.简单的是或否.如果是/否,那么如何和位解释.如果可能的话,请讨论效率.

Era*_*ran 7

是的,您可以使用flatMap将您的单个元素映射StreamStream多个元素中,然后将它们展平为单个元素Stream:

Set<Long> memberIds = 
    marksDistribution.stream()
                     .flatMap (marksDistribution -> Stream.of(marksDistribution.getStudentId(), marksDistribution.getTeacherId()))
                     .collect(Collectors.toSet());
Run Code Online (Sandbox Code Playgroud)

  • @Eran 1+来自我,如果你有jdk-9,你可以使用flatMapping收集器:list.stream().collect(Collectors.flatMapping((MarksDistribution md) - > Stream.of(md.getStudentId(),md .getTeacherId()),Collectors.toSet())); (4认同)
  • @Eugene:与所有Stream操作一样,我只在必要时使用Collector对应物.您几乎可以将每个Stream操作表示为仅收集器操作,尤其是Java 9,但它很难读取... (3认同)

Ale*_* C. 5

您可以使用 collect 的 3-args 版本:

Set<Long> memberIds = 
    marksDistribution.parallelStream()
                     .collect(HashSet::new, 
                              (s, m) -> {
                                   s.add(m.getStudentId());
                                   s.add(m.getTeacherId());
                               }, Set::addAll);
Run Code Online (Sandbox Code Playgroud)

您当前的版本可能会产生错误的结果,因为您是在非线程安全集合中并行添加元素。因此,您可能在集合中有多次相同的值。

  • @balboa_21 问题是你所做的有缺陷。在考虑效率之前,您应该考虑正确性。也就是说,使用 `collect` 是使用流获得你想要的东西的规范方式。 (5认同)
  • @balboa_21 仍然使用`collect`。否则,如果有人决定在未来将 `.stream()` 更改为 `.parallelStream()`,你会留下一段无法工作的代码。 (4认同)
  • @balboa_21:如果您不使用并行操作,则可以直接在集合上使用 `forEach`,即根本不使用 Stream 操作。 (3认同)