在java 8 lambdas中,如何访问流中的原始对象?

时间:2016-05-18 12:14:41

标签: lambda java-8 java-stream

假设我有一个'A'列表

List<A> as;

如果我想对每个A进行相当多的处理,并且在处理结束时,我想把结果放在A的另一个字段中,最好的方法是什么?< / p>

as.stream().
map(a -> a.getX()).
filter(x -> x != null).
map(x -> lookup.get(x)).

At this point how to say y -> a.setLookedUpVal(y)?

我在lambda链中失去了对'a'的引用。有没有办法存储它并返回它或什么?

2 个答案:

答案 0 :(得分:6)

如果您有更复杂的场景或由于某种原因不喜欢@Aaron答案,您可以执行flatMap捕获技巧,为每个外部元素创建一个元素流:

as.stream().
   flatMap(a -> Stream.of(a.getX()).
      filter(x -> x != null).
      map(x -> a)).
   forEach(System.out::println);

这里我们有嵌套的每元素流,您可以在其中执行任何无状态流操作(mapfilterpeekflatMap)元件。在不需要原始元素后,关闭flatMap并继续原始流。例如:

Stream.of("a", "bb", "ccc", "dd", "eeee")
    .flatMap(a -> Stream.of(a.length())
            .filter(x -> x > 2)
            .map(x -> a))
    .forEach(System.out::println);
// prints "ccc" and "eeee".

或两个过滤器:

Stream.of("a", "bb", "ccc", "dd", "eeee")
    .flatMap(a -> Stream.of(a.length())
            .filter(x -> x > 2)
            .map(x -> a.charAt(0)) // forget the length, now check the first symbol
            .filter(ch -> ch == 'c')
            .map(x -> a)) // forget the first symbol, reverting to the whole string
    .forEach(System.out::println);
// prints only "ccc"

当然这些简单的场景可以像@Aaron建议的那样重写,但在更复杂的情况下,flatMap-capture可能是合适的解决方案。

答案 1 :(得分:4)

我不知道您是否可以访问未修改的元素,但您可以通过以下方式重新编写操作链:

as.stream()
  .filter(a -> a.getX() != null)
  .forEach(a -> a.setLookedUpVal(lookup.get(a.getX()))

现在我明白它会使它变得更复杂,并且在解决你的现实问题时可能没什么兴趣 然而,它具有与Stream<A>一起工作的优点,在某些情况下,它可以比在不同步骤中具有不同类型更简单和更具可扩展性。