How to perform nested 'if' statements using Java 8/lambda?
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
)
You could declare a body for a lambda. For example:
Runnable run = () -> System.out.println("Hey");
Could be
Runnable run = () -> {
System.out.println("Hey");
};
Within that body, you can create nested statements:
Runnable run = () -> {
int num = 5;
if(num == 5) {
System.out.println("Hey");
}
};
Use flatMap
as you are trying to add elements into the pipeline or a 1-to-many mapping. Map is a one to one mapping.
ArrayList<Integer> result = (ArrayList<Integer>) IntStream.rangeClosed(1, 10)
.boxed()
.filter(i -> 10 % i == 0)
.flatMap((Integer i) -> {return i!=5 ? Stream.of(i, (10/i)):Stream.of(i);})
.collect(Collectors.toList());
This results in the same list as
ArrayList<Integer> result2 = new ArrayList<Integer>();
for (int i = 1; i <= 10; i++) {
if (10 % i == 0) {
result2.add(i);
if (i != 5) {
result2.add(10 / i);
}
}
}
In case your wondering which way is faster the loop method is ~3 times faster than using streams.
Benchmark Mode Cnt Score Error Units
testStreams.Bench.loops avgt 5 75.221 ± 0.576 ns/op
testStreams.Bench.streams avgt 5 257.713 ± 13.125 ns/op