1. Overview

In this tutorial, we’re going to demonstrate how to implement if/else logic with Java 8 Streams. As part of the tutorial, we’ll create a simple algorithm to identify odd and even numbers.

We can take a look at this article to catch up on the Java 8 Stream basics.

2. Conventional if/else Logic Within forEach()

First of all, let’s create an Integer List and then use conventional if/else logic within the Integer stream forEach() method:

List<Integer> ints = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

ints.stream()
    .forEach(i -> {
        if (i.intValue() % 2 == 0) {
            Assert.assertTrue(i.intValue() % 2 == 0);
        } else {
            Assert.assertTrue(i.intValue() % 2 != 0);
        }
    });

Our forEach method contains if/else logic that verifies whether the Integer is an odd or even number using the Java modulus operator.

Typically, we can rewrite the previous if/else logic using a custom consumer. In short, a consumer is a functional interface that accepts a parameter and returns nothing. So, let’s see it in action:

List<Integer> ints = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Consumer<Integer> integerParityAsserter = i -> {
    if (i % 2 == 0) {
        Assert.assertTrue(i + " is not even", i % 2 == 0);
    } else {
        Assert.assertTrue(i + " is not odd", i % 2 != 0);
    }
};

ints.stream()
    .forEach(integerParityAsserter);

As we can see, our custom consumer acts as an asserter that checks the given integer parity, and we can pass it directly to the forEach() method.

3. if/else Logic With filter()

Secondly, let’s look at a more elegant implementation using the Stream filter() method:

Stream<Integer> evenIntegers = ints.stream()
    .filter(i -> i.intValue() % 2 == 0);
Stream<Integer> oddIntegers = ints.stream()
    .filter(i -> i.intValue() % 2 != 0);

evenIntegers.forEach(i -> Assert.assertTrue(i.intValue() % 2 == 0));
oddIntegers.forEach(i -> Assert.assertTrue(i.intValue() % 2 != 0));

Above, we implement the if/else logic using the Stream filter() method *to separate the Integer List into two Streams, one for even integers and another for odd integers.*

4. Using Collectors#groupingBy

Another solution would be to use the groupingBy() method. At its core, this method creates groups from data based on a specified criterion. So, let’s see it in action:

List<Integer> ints = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

Map<String, List<Integer>> resultMap = ints.stream()
    .collect(Collectors.groupingBy(i -> i % 2 == 0 ? "even" : "odd"));

Assert.assertEquals(Arrays.asList(2, 4, 6, 8, 10), resultMap.get("even"));
Assert.assertEquals(Arrays.asList(1, 3, 5, 7, 9), resultMap.get("odd"));

Notably, we pass a ternary operator that returns “even” if the integer is even and “odd” otherwise. Furthermore, the groupingBy() method relies on the specified criteria to group the integers into two separate groups. The first group describes even integers and the other one denotes odd ones.

5. Using Collectors#partitioningBy

Alternatively, we can use the partitioningBy() method. It’s a specialized version of the groupingBy() method that accepts a Predicate as a parameter. As the name implies, it divides the data into exactly two partitions based on a specified Predicate.

So, let’s see in practice:

List<Integer> ints = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

Map<Boolean, List<Integer>> resultMap = ints.stream()
    .collect(Collectors.partitioningBy(i -> i % 2 == 0));

Assert.assertEquals(Arrays.asList(2, 4, 6, 8, 10), resultMap.get(true));
Assert.assertEquals(Arrays.asList(1, 3, 5, 7, 9), resultMap.get(false));

The partitioningBy() method returns a Map that stores Boolean as keys and List as values. Here, the list associated with the key “true” contains all elements matching the given predicate, which denotes even integers. On the other hand, the key “false” points to the list that represent odd integers.

6. Conclusion

In this quick article, we’ve explored how to create a Java 8 Stream and how to implement if/else logic using the forEach() method. Furthermore, we’ve seen how to use a custom consumer to achieve the same outcome.

Along the way, we learned how to use the Stream filter method, Collectors#groupingBy, and Collectors#partitioningBy to achieve a similar result more elegantly.

Finally, the complete source code used in this tutorial is available over on GitHub.