The best way to do this with streams is to use reduce
:
// make a transformer that combines all of them as one
Transformer combinedTransformer =
// the stream of transformers
transformers.stream()
// combine all the transformers into one
.reduce(
// apply each of the transformers in turn
(t1, t2) -> x -> t2.apply(t1.apply(x)))
);
// the stream of strings
strings.stream()
// transform each string with the combined transformer
.map(combinedTranformer::apply);
Of course, this assumes that transformers
is non-empty; if there is a possibility that it is empty, than it is simple enough to use the two-argument overload of reduce
instead, like so (this assumes Tranformer
is a functional interface):
// make a transformer that combines all of them as one
Transformer combinedTransformer =
// the stream of transformers
transformers.stream()
// combine all the transformers into one
.reduce(
// the no-op transformer
x -> x,
// apply each of the transformers in turn
(t1, t2) -> x -> t2.apply(t1.apply(x)))
);
// the stream of strings
strings.stream()
// transform each string with the combined transformer
.map(combinedTranformer::apply);
The reason you got a compiler error is that, as the error says, outside variables used in a lambda expression must be effectively final; that is, declaring them final
(if they aren't already) must not change the meaning of the program, or change whether or not it compiles. Using a mutable assignment in a lambda is therefore generally forbidden, and with good reason: mutation screws up parallelization, and one of the major reasons lambdas were included in Java 8 was to allow easier parallel programming.
Generally speaking, whenever you want to "sum up" results in some way, reduce
(in any of its three overloads) is your go-to method. Learning how to use map
, filter
, reduce
, and flatMap
effectively is very important when working with Stream
s.