Search code examples
javalambdajava-8functional-programmingnested-if

How to perform nested 'if' statements using Java 8/lambda?


I have the following code and would like to implement it using lambda functions just for fun. Can it be done using the basic aggregate operations?

List<Integer> result = new ArrayList<>();

for (int i = 1; i <= 10; i++) {
    if (10 % i == 0) {
        result.add(i);
        if (i != 5) {
            result.add(10 / i);
        }
    }
}

Using lambda:

List<Integer> result = IntStream.rangeClosed(1, 10)
                                .boxed()
                                .filter(i -> 10 % i == 0)
                                // a map or forEach function here?
                                // .map(return 10 / i -> if i != 5)
                                .collect(Collectors.toList());

Solution

  • The essential observation here is that your problem involves a non-isomorphic transformation: a single input element may map to zero, one, or two output elements. Whenever you notice this, you should immediately start looking for a solution which involves flatMap instead of map because that's the only way to achieve such a general transformation. In your particular case you can first apply filter for a one-to-zero element mapping, then flatMap for one-to-two mapping:

    List<Integer> result =
        IntStream.rangeClosed(1, 10)
                 .filter(i -> 10 % i == 0)
                 .flatMap(i -> i == 5 ? IntStream.of(i) : IntStream.of(i, 10 / i))
                 .boxed()
                 .collect(toList());
    

    (assuming import static java.util.stream.Collectors.toList)