假设有一个集合需要先修改然后过滤:
Collection<MyObject> collection = ...
Stream<MyObject> dummyVariable = collection.stream();
dummyVariable.forEach(i -> i.callModifyingFunc(args));
return dummyVariable.filter(i -> i.isNeeded);
因为forEach有void
返回类型,所以在没有dummyVariable
的情况下编写代码是不可能的。是否有任何解决方法可以在一个链中编写所有内容:
Collection<MyObject> collection = ...
return Stream<MyObject> dummyVariable = collection.stream().forEach(i -> i.callModifyingFunc(args)).filter(i -> i.isNeeded);
答案 0 :(得分:2)
只需使用map而不是forEach来链接管道操作:
collection.stream()
.map(i -> i.callModifyingFunc(args))
.filter(i -> i.isNeeded);
答案 1 :(得分:2)
如果将Stream
返回给调用者,则无法控制最终由调用者链接的终端操作。终端操作可能会处理所有元素,但它也可能是短路的,甚至可能是调用者放弃流而根本不应用终端操作。
如果修改仅用于记录元素是否已被处理,peek
是正确的选择。
但是如果你想在任何一种情况下对每个元素都应用修改,那就直接进行:
Collection<MyObject> collection = ...
collection.forEach(i -> i.callModifyingFunc(args));
return collection.stream().filter(i -> i.isNeeded);
如果您想确保仅在呼叫者开始终端操作时进行修改,则会更复杂:
Collection<MyObject> collection = ...
Spliterator<MyObject> sp = collection.spliterator();
return StreamSupport.stream(() -> {
collection.forEach(i -> i.callModifyingFunc(args));
return sp;
}, sp.characteristics(), false)
.filter(i -> i.isNeeded);
这将在Stream处理开始之前,即在执行终端操作之前执行所有元素的修改。
但你应该重新考虑你的要求。必须在流处理之前修改所有元素听起来有问题。如果两个客户获得流,会发生什么?