Small question regarding Java and its Stream API, especially the reduce()
operation.
I have as input some Stream of integers.
The integers go from -1
inclusive, to a positive integer. In the mathematical notation, it would be [-1,n]
.
Note that the smallest possible number is -1
(minus 1). It cannot be -2
, -3
, etc., the smallest is -1
.
I would like to write a reduce function which does:
Case A – if the stream contains numbers from 0
to n
, basically, there is no -1
in the stream, return the minimum number of the stream.
Stream<Integer> casea = Stream.of(2, 0, 4);
For above case A example, to return 0
.
Case B – if the stream contains only -1
, there is nothing else other than -1
, return -1
.
Stream<Integer> caseb = Stream.of(-1, -1, -1);
For above case B example, to return -1.
Case C – if the stream contains any -1, and any non -1, return the minimum number that is not -1.
Stream<Integer> casec = Stream.of(-1, 2, 5);
For above case C example, return 2
(and not -1
).
I am having trouble crafting this reduce function.
What I have tried:
So far, I tried:
.reduce(Integer.MAX_VALUE, Integer::min);
Unfortunately, it is not correct. It is returning the correct result for case a and b.
However, it will return -1 for the case c, where I would like to return the smallest non -1 integer, since it has something other than -1 in the stream.
How can I apply reduce
operation to meat the requirements?
Advertisement
Answer
To find the smallest element that is different from -1
, firstly, apply filter()
to retain only non-minus-one elements in the stream and then apply min()
.
As a default value, which would be returned if the stream appears to be empty, provide -1
.
public static int getSmallestNonMinusOne(List<Integer> list) { return list.stream() .mapToInt(Integer::intValue) .filter(i -> i != -1) .min() .orElse(-1); }
Alternatively, if you want to use reduce()
you can re-write the code like this:
public static int getSmallestNonMinusOne(List<Integer> list) { return list.stream() .mapToInt(Integer::intValue) .filter(i -> i != -1) .reduce(Integer::min) .orElse(-1); }
Note: that min
is basically a specialized form of reduction, and from the perspective of readability the first version is preferred one.
main()
public static void main(String[] args) { System.out.println(getSmallestNonMinusOne(List.of(-1, 0, 8))); System.out.println(getSmallestNonMinusOne(List.of(-1, -1, -1))); System.out.println(getSmallestNonMinusOne(List.of(-1, 2, 5))); System.out.println(getSmallestNonMinusOne(List.of())); }
Output:
0 // -1, 0, 8 -1 // only -1 elements in the source 2 // -1, 2, 5 -1 // source is empty