PAA
PAA

Reputation: 12063

Reduce Integer.min doesn't return lowest element

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

Answers (6)

Malt
Malt

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

VHS
VHS

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

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

PAA
PAA

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

Aleh Maksimovich
Aleh Maksimovich

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

Dalancer
Dalancer

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

Related Questions