java streams How to filter a collection to two new collections

I tried to create two lists - odds and evens as follows:

public static void main(String[] args) {
    List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 5, 8, 13, 21));
    List<Integer> odds = new ArrayList<>();
    List<Integer> evens = new ArrayList<>();
    numbers.stream().forEach(x -> x % 2 == 0 ? evens.add(x) : odds.add(x));
}

But it gave me incompatible types error (bad return type in lambda expression missing return value)

What is the best way to filter a collection to two new collections?

Jon Skeet
people
quotationmark

Well, you can make your existing code compile with a trivial modification:

 public static void main(String[] args) {         
     List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 5, 8, 13, 21));
     List<Integer> odds = new ArrayList<>();
     List<Integer> evens = new ArrayList<>();
     numbers.stream().forEach(x -> (x % 2 == 0 ? evens : odds).add(x));
 }

The conditional ?: operator is an expression, which isn't a valid statement on its own. My modified code changes the use of the conditional operator to just select which list to add to, and then calls add on it - and that method invocation expression is a valid statement.

An alternative would be to collect using Collectors.partitioningBy - although in this particular case that would probably be more confusing code than what you've got.

people

See more on this question at Stackoverflow