List<String> evens = someList.stream()
.filter(i -> i % 2 == 0)
.toList()
For-comprehension Version:
ArrayList<String> evens = for (int i : myArrayOrIterable) {
if (i % 2 == 0) yield i;
}
Compiles to:
ArrayList<String> evens = new ArrayList<>();
for (int i : myArrayOrIterable) {
if (i % 2 == 0) evens.add(i);
}
If the return-type of a for-expression is not specified, a Collection is returned.
One could make the return type HashSet and it will work as expected, because ArrayList, HashSet, and any container that wants to support for-expressions implements Collection, which requires a 0-arg constructor (Javadoc: "should provide two "standard" constructors: a void (no arguments) constructor..."), and an add() method. If interfaces someday allow us to require a 0-arg constructor (which would improve Spring and Hibernate) then the for-expression return type could be opened to any class implementing an interface.
There are many reasons why for-expressions are better than Stream for simple tasks like converting between collection types.
In complex cases, a regular for statement is better than both Stream or for-expressions.