This question already has an answer here:
I'm studying for 1z0-809 : Java SE 8 Programmer II using Enthuware's mocktests.
Encountering this question.
List<Integer> ls = Arrays.asList(3,4,6,9,2,5,7); System.out.println(ls.stream().reduce(Integer.MIN_VALUE, (a, b)->a>b?a:b)); //1 System.out.println(ls.stream().max(Integer::max).get()); //2 System.out.println(ls.stream().max(Integer::compare).get()); //3 System.out.println(ls.stream().max((a, b)->a>b?a:b)); //4
Which of the above statements will print 9?
Answer is
1 and 3
But there is something else. I don't get why
System.out.println(ls.stream().max(Integer::max).get()); // PRINTS 3
I tried to debug it using peek
but it doesn't help me understanding.
I tried to sort ls
using Integer::max
and Integer::compare
ls.sort(Integer::max); // [3, 4, 6, 9, 2, 5, 7]
ls.sort(Integer::compare); // [2, 3, 4, 5, 6, 7, 9]
Of course, I get the fact that Integer::max
is not a Comparator, hence it has the same signature of one.
For me, max
should be 7
in the first case since it is the last element like when I sorted with Ìnteger::compare
Could someone break it down to something simple?
Integer.max(a, b)
will return the greater value of the given a
and b
. If you use that result somehow as a comparator, a positive value returned will be regarded as meaning that a > b
so a
will be kept.
The first two elements are 3 and 4. Both are positive. Integer.max(3, 4) = 4 > 0
. So you're effectively saying that 3 > 4
with such a comparator, so 3 is kept. Then, the same goes for the rest: Integer.max(3, 6) = 6 > 0
, so 3 is considered the max, etc.
The contract of a comparator method (on arguments first
, second
) is:
- return 0 if
first
equalssecond
- return negative value if
first < second
- return positive value if
first > second
The max
method with only positive values will always return a positive value. When interpreting the return value according to the comparator contract, a positive value means first > second
. As a result, the ordering of items will not change, they appear to be "ordered".
This is unbelievably confusing.
We are trying use Integer::max
as a comparator. Since all the numbers in the question are positive, the answer is always interpreted as meaning that the first argument of compare(a, b)
is "greater" than the second.
One quirk of Collections.sort
is that when you have a list [a, b]
, the method is programmed in such a way that it is compare(b, a)
that is called, rather than compare(a, b)
(which would seem more sensible). Hence if compare
returns a positive number, it looks like b > a
, so the list does not need sorting.
That is why list.sort
does nothing.
However it just happens that Stream.max
is programmed the other way around, i.e. the first comparison is compare(3, 4)
, so it looks like 3
is the maximum.
来源:https://stackoverflow.com/questions/36118832/stream-maxintegermax-unexpected-result