I want to achieve something like this:
items.stream() .filter(s-> s.contains("B")) .forEach(s-> s.setState("ok")) .collect(Collectors.toList());
filter, then change a property from the filtered result, then collect the result to a list. However, the debugger says:
Cannot invoke
collect(Collectors.toList())
on the primitive typevoid
.
Do I need 2 streams for that?
The forEach
is designed to be a terminal operation and yes - you can't do anything after you call it.
The idiomatic way would be to apply a transformation first and then collect()
everything to the desired data structure.
The transformation can be performed using map
which is designed for non-mutating operations.
If you are performing a non-mutating operation:
items.stream() .filter(s -> s.contains("B")) .map(s -> s.withState("ok")) .collect(Collectors.toList());
where withState
is a method that returns a copy of the original object including the provided change.
If you are performing a side effect:
items.stream() .filter(s -> s.contains("B")) .collect(Collectors.toList()); items.forEach(s -> s.setState("ok"))
Replace forEach
with map
.
items.stream() .filter(s-> s.contains("B")) .map(s-> {s.setState("ok");return s;}) .collect(Collectors.toList());
forEach
and collect
are both terminal operations - Streams must have just one. Anything that returns a Stream<T>
is a intermediate operation
, anything other is a terminal operation
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With