Reputation: 12063
I am doing some research on the stream reduce
and trying to run the very simple program.
Why Integer.min
doesn't return the minimum number like Integer.min
return the maximum number ?
public class Reducing {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(3,4,5,1,2);
Integer sum = numbers.stream().reduce(0, (a, b) -> a+ b);
System.out.println("REDUCE : "+sum);
int sum2 = numbers.stream().reduce(0, Integer::sum);
System.out.println(sum2);
int max = numbers.stream().reduce(0, (a, b) -> Integer.max(a, b));
System.out.println("MAX == > "+max);
int min = numbers.stream().reduce(0, (a, b) -> Integer.min(a, b));
System.out.println("MIN == > "+min);
}
}
Output ==>
REDUCE : 15
15
MAX == > 5
MIN == > 0
Upvotes: 9
Views: 825
Reputation: 30335
You're passing 0
as the initial value into your reduce: reduce(0, (a, b) -> Integer.min(a, b))
. It's therefore the smallest number. Pass Integer.MAX_VALUE
instead or use the following:
Optional<Integer> min = numbers.stream().reduce((a, b) -> Integer.min(a, b));
System.out.println("MIN == > " + min.get());
Or, an even without the lambda:
Optional<Integer> min = numbers.stream().reduce(Integer::min)
There's also an option of doing it reduce.and using min
instead:
Optional<Integer> min = numbers.stream().min(Comparator.naturalOrder());
Upvotes: 5
Reputation: 10184
The reduce
method takes the identity
- the first argument, 0 in your case, in consideration while applying the given reduction
function. The supplied identity acts as both an initial value and a default value.
As per the Java docs, reduce
works on the following algorithm:
T result = identity; for (T element : this stream) result = accumulator.apply(result, element) return result;
Hence, while evaluating the Integer.min
, the value of 0 is also included in the calculation.
A solution is to not supply any identity or an identity that is greater than or equal to the smallest value in the list.
Upvotes: 0
Reputation: 48307
the reduce
operation works as:
you have this list:
Arrays.asList(3,4,5,1,2);
and do
reduce(0, (a, b) -> Integer.max(a, b));
which means:
compare all the pair a, b and the first element must 0 as precesor
so the operation will be
Integer.max(a, b)
Integer.max(0, 3) => return 3
Integer.max(3, 4) => return 4
Integer.max(4, 5) => return 5
Integer.max(5, 1) => return 5
Integer.max(5, 2) => return 5
and for the min, the same analogy applies...
Integer.min(a, b)
Integer.min(0, 3) => return 0
Integer.min(0, 4) => return 0
Integer.min(0, 5) => return 0
Integer.min(0, 1) => return 0
Integer.min(0, 2) => return 0
thus the result max:5 and min:0
Upvotes: 3
Reputation: 12063
I think I need to use below. Optional is a container object which is used to contain not-null objects. Optional object is used to represent null with absent value. ... It is introduced in Java 8 and is similar to what Optional is in Guava.
Optional<Integer> min = numbers.stream().reduce(Integer::min);
min.ifPresent(System.out::println);
Here is the oracle article : http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
Upvotes: 0
Reputation: 2650
You are supplying 0
as identity item to min
. This value will also used in computations.
int min = numbers.stream().reduce(0, (a, b) -> Integer.min(a, b));
So virtually it is like having
Arrays.asList(0,3,4,5,1,2)
You shuold omit the identity element in your example
int min = numbers.stream().reduce((a, b) -> Integer.min(a, b)).get();
Upvotes: 15
Reputation: 1
The reduce operation in this example takes two arguments:
identity: The identity element is both the initial value of the reduction and the default result if there are no elements in the stream. In this example, the identity element is 0; this is the initial value of the sum of ages and the default value if no members exist in the collection roster.
Use numbers.get(0)
instead of 0, so the initial value would be the first item in your list
Upvotes: 0