是否有解决方法"返回"来自forEach方法的流?

时间:2016-11-23 02:49:51

标签: foreach java-8 java-stream

假设有一个集合需要先修改然后过滤:

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);

2 个答案:

答案 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处理开始之前,即在执行终端操作之前执行所有元素的修改。

但你应该重新考虑你的要求。必须在流处理之前修改所有元素听起来有问题。如果两个客户获得流,会发生什么?