在Java8Lambdas中,如何访问流中的原始对象?
假设我有一个“a”的列表在Java8Lambdas中,如何访问流中的原始对象?,lambda,java-8,java-stream,Lambda,Java 8,Java Stream,假设我有一个“a”的列表 List<A> as; 在lambda链中,我失去了对“a”的引用。有没有办法存储它并引用它或其他什么?我不知道您是否可以访问未修改的元素,但您可以通过以下方式修改操作链: as.stream() .filter(a -> a.getX() != null) .forEach(a -> a.setLookedUpVal(lookup.get(a.getX())) 现在我明白了,这会使问题变得更复杂,并且可能对解决现实世界的问题不感兴趣
List<A> as;
在lambda链中,我失去了对“a”的引用。有没有办法存储它并引用它或其他什么?我不知道您是否可以访问未修改的元素,但您可以通过以下方式修改操作链:
as.stream()
.filter(a -> a.getX() != null)
.forEach(a -> a.setLookedUpVal(lookup.get(a.getX()))
现在我明白了,这会使问题变得更复杂,并且可能对解决现实世界的问题不感兴趣。但是,它的优点是始终与
流一起工作,这在某些情况下比在不同的步骤中使用不同的类型更简单、更可扩展。如果您有更复杂的场景或出于某种原因不喜欢@Aaron answer,您可以执行flatMap捕获技巧,为每个外部元素创建一个元素流:
as.stream().
flatMap(a -> Stream.of(a.getX()).
filter(x -> x != null).
map(x -> a)).
forEach(System.out::println);
这里我们有嵌套的每个元素流,您可以在其中执行任何无状态流操作(map
,filter
,peek
和flatMap
),并引用原始元素。在原始元素变得不必要后,关闭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建议的那样重写,但在更复杂的情况下,平面图捕获可能是合适的解决方案。如果查找绑定到x
,我建议更改代码以获得类似a.lookup(lookup::get)
的内容。然后,您将为(a:as)if(a.getX()!=null)a.setLookedUpVal(lookup.get(a.getX()))使用一个简单的forEach
或者,如果getX()
很昂贵,那么对于(A:as){X X=A.getX();如果(X!=null)A.setLookedUpVal(lookup.get(X));}
。在决定使用之前,请将每个基于流的解决方案与之进行比较…或.flatMap(a->a.length()>2&&a.charAt(0)='c'?Stream.of(a):null)
,这几乎与使用过滤器一样简洁…
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"