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?
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 ofcompare(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 iscompare(b, a)
that is called, rather thancompare(a, b)
(which would seem more sensible). Hence ifcompare
returns a positive number, it looks likeb > 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 iscompare(3, 4)
, so it looks like3
is the maximum.The contract of a comparator method (on arguments
first
,second
) is:first
equalssecond
first < second
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 meansfirst > second
. As a result, the ordering of items will not change, they appear to be "ordered".Although this doesn't answer the question, a possible solution to your problem would be:
The
mapToInt(e -> e)
method uses a lambda expression to transform every element in the stream to a integer value and returns aIntStream
wheremax()
method can then be called. Note thatmax()
returns anOptionalInteger
and so agetAsInt()
or aorElse(0)
method call is nedeed.You can take a look at the docs for a more in-depth answer: IntStream, OptionalInt
Integer.max(a, b)
will return the greater value of the givena
andb
. If you use that result somehow as a comparator, a positive value returned will be regarded as meaning thata > b
soa
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 that3 > 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.You need to replace
with
The problem here is that the abstract method
compare
is declared to return anint
value and that is also satisfied by the signature ofInteger.max
along with methodInteger.compare
in theInteger
class, hence the representationInteger::max
is inferred as a validComparator
. Though the compare method is expected to be implemented such as it:In your current scenario, the code always ends up returning a positive value (given the input) and therefore the first element in comparison is considered to be greater always and thus returned accordingly.