You should avoid using forEach on Java as much as possible, I think
Collection shouldn't be updated in lambda explanation
Sometimes I see these kind of code.
List<X> list = new ArrayList<>(); /*AnyCollection*/.forEach() .map(t -> list.add(t.getXXXX()));
I think it's bad code.
It's not thread safe
If you use parallel stream on above code...
List<X> list = new ArrayList<>(); /*AnyCollection*/.forEach().parallelStream() .map(x -> list.add(x.getXXXX()));
it doesn't work correctly because ArrayList's add is not thread safe. "Sometimes" strange null will be added in the list. *1
Of course, you can avoid this trouble if you don't use parallel stream.
However, there is no assuarance that nobody change this part to parallel in the future.
It's not "Function"
Lambda explanations accept only final (or actually final) variable from out of lambda. So any variables doesn't accept new value.*2
On the other hand, "update" isn't restricted like "add to list" or setter.
However, even it's not restricted, we shouldn't do any update against variable, which is defined out of lambda.
Idiom for making collection is existing
This is most common way to make list.
List<X> list = /*AnyCollection*/.stream() //parallel stream can be used .map(X::getXXXX) .collect(Collector.toList());
This format shows clearly that you want to make list better than previous sample.