说有一个收集需要先修改然后过滤:
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);
只需使用映射而不是foreach链接管道操作:
collection.stream()
.map(i -> i.callModifyingFunc(args))
.filter(i -> i.isNeeded);
如果将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);
这将在流处理开始之前(即执行终端操作之前)对所有元素进行修改。
,但是您应该重新考虑您的要求。必须在流处理之前修改所有元素听起来有问题。如果两个客户获取流?