Reputation: 33544
Say that there is a collection which is needed to be modified first and then filtered:
Collection<MyObject> collection = ...
Stream<MyObject> dummyVariable = collection.stream();
dummyVariable.forEach(i -> i.callModifyingFunc(args));
return dummyVariable.filter(i -> i.isNeeded);
Because forEach has void
return type is it impossible to write code without dummyVariable
. Is there any workaround to write all in one chain:
Collection<MyObject> collection = ...
return Stream<MyObject> dummyVariable = collection.stream().forEach(i -> i.callModifyingFunc(args)).filter(i -> i.isNeeded);
Upvotes: 0
Views: 141
Reputation: 298153
If you return a Stream
to a caller, you have no control over the terminal operation eventually chained by the caller. The terminal operation might process all elements, but it also might be short-circuiting and it might even be the case that the caller abandons the stream without ever applying a terminal operation at all.
If the modification is intended to just record whether an element has been processed, peek
is the right choice.
But if you want to apply a modification to every element in either case, just do it straight-forward:
Collection<MyObject> collection = ...
collection.forEach(i -> i.callModifyingFunc(args));
return collection.stream().filter(i -> i.isNeeded);
If you want to ensure that the modification is only made when the caller commences a terminal operation, it’s a bit more complicated:
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);
This will perform the modification of all elements right before the Stream processing starts, i.e. before the execution of the terminal operation.
But you should rethink your requirement. Having to modify all elements before a stream processing sounds questionable. What will happen if two clients acquire a stream?
Upvotes: 2
Reputation: 3093
Just use map instead of forEach to chain the pipeline operations:
collection.stream()
.map(i -> i.callModifyingFunc(args))
.filter(i -> i.isNeeded);
Upvotes: 2