Page 1 of 1

About Question enthuware.ocpjp.v8.2.1792 :

Posted: Thu Sep 01, 2016 3:49 am
by ramy6_1
Hello ,

I tried option number 2 on eclipse and it print 3 as you mentioned , can you please explain a little bit why options 2 and 4 prints the value 3 ?

Re: About Question enthuware.ocpjp.v8.2.1792 :

Posted: Fri Sep 02, 2016 1:36 am
by admin
Please go through the explanation for #2 and let me know which part do you not understand so that I can comment.
-Paul.

Re: About Question enthuware.ocpjp.v8.2.1792 :

Posted: Sun Sep 11, 2016 4:44 am
by ramy6_1
Hello ,

"However, Integer.max works very differently from Integer.compare. The max method returns the maximum of two numbers while the compare method returns a difference between two numbers."

I tried the following to send an explicit Comparator

Comparator<Integer> c2 = (x1, x2) -> x1.compareTo(x2);
System.out.println(ls.stream().max(c2).get()); // print 9

Comparator<Integer> c3 = (x1, x2) -> Integer.max(x1, x2);
System.out.println(ls.stream().max(c3).get()); // print 3

So why difference working but maximum doesn't work ?

You mentioned "All you need to implement this interface using a lambda expression is a reference to any method that takes two arguments and returns an int"

That means max - that takes two arguments and return int should work here - since compareTo takes only one arguments

Re: About Question enthuware.ocpjp.v8.2.1792 :

Posted: Sun Sep 11, 2016 11:07 am
by admin
What do you mean by "doesn't work"?? Do you mean doesn't compile or doesn't do what is expected i.e. return the correct value?

Re: About Question enthuware.ocpjp.v8.2.1792 :

Posted: Mon Sep 12, 2016 5:11 am
by ramy6_1
I mean it doesn't get the maximum.

Re: About Question enthuware.ocpjp.v8.2.1792 :

Posted: Mon Sep 12, 2016 10:43 am
by admin
Because Stream's max method is written to work with a Comparator. It expects that the function used for comparison will return the difference between the two numbers. It is coded accordingly. So I am not sure why would you expect it to work with Integer.max method? Integer.max method doesn't return the difference of two numbers.

Re: About Question enthuware.ocpjp.v8.2.1792 :

Posted: Mon Oct 03, 2016 9:31 am
by lucian
Maybe this will make understanding easier the difference between Integer.max() and Integer.compare() methods usage in a stream max method

Code: Select all

        System.out.println("USING Integer.max()");
        System.out.println(ls.stream().max((o1, o2) -> {System.out.print(o1);
                                                        System.out.print(o2);
                                                        int max = Integer.max(o1, o2);
                                                        System.out.print(max);
                                                        System.out.print("\t");
                                                        return max;})
                                      .get());
        System.out.println("USING Integer.compare()");
        System.out.println(ls.stream().max((o1, o2) -> {System.out.print(o1);
                                                        System.out.print(o2);
                                                        int max = Integer.compare(o1, o2);
                                                        System.out.print(max);
                                                        System.out.print("\t");
                                                        return max;})
                                      .get());

Code: Select all

USING Integer.max()
344	366	399	323	355	377	3
USING Integer.compare()
34-1	46-1	69-1	921	951	971	9

Re: About Question enthuware.ocpjp.v8.2.1792 :

Posted: Sat Jun 03, 2017 11:16 am
by sedletskiyv
I think the misunderstanding is that the Comparable interface accepts any positive value comparing something with something, so when max() is used even the first element (3) compared with any other (9) is ok, as well as 9 compared to 3.

Re: About Question enthuware.ocpjp.v8.2.1792 :

Posted: Fri Jun 29, 2018 4:23 am
by anojer8
In line 1, the code is:
System.out.println(ls.stream().reduce(Integer.MIN_VALUE, (a, b)->a>b?a:b)); //1

the identity is Integer.MIN_VALUE, if I change it to 0 or -10 or whatever, it just have no effect on the result.
What is the reason for that? Is it because it isn't used in the BinaryOperator?

Re: About Question enthuware.ocpjp.v8.2.1792 :

Posted: Fri Jun 29, 2018 5:23 am
by admin
The Identity value acts as the initial element for the reduction. What if you change your identity value to 10 and have only one element in the stream with value < 10? Or what if there are no elements in the stream? What if your lambda returns a+b instead of a>b?a:b ?

Re: About Question enthuware.ocpjp.v8.2.1792 :

Posted: Fri Jul 13, 2018 12:42 pm
by __JJ__
For anyone who's just come to this, I think the easiest way to explain it is this:
1. they all compile because the function signatures match the requirement of Stream.max which is for a method signature that matches Comparator's int compare(T o1, T o2) method
2. 2 and 4 don't work because they always return a positive number, which the Stream.max function interprets as meaning: the first argument is larger than the second (remember every implementation of compare is supposed to return a +ve number if the first operand is larger than the second), so what happens is it keeps the first and moves on to the comparison of the next element.

That's my understanding; apologies if it's incorrect.

Re: About Question enthuware.ocpjp.v8.2.1792 :

Posted: Thu Jul 26, 2018 5:35 pm
by __JJ__
The Stream.max method requires a Comparator. All you need to implement this interface using a lambda expression is a reference to any method that takes two arguments and returns an int.
I know what you mean but it's still important that the types for the arguments are the same and non-primitive and that if the Comparator is untype the only valid type is Object:

Code: Select all

          Comparator c1 = (a,b) -> 1;                           //OK
          Comparator c2 = (int a, int b) -> 1;                  //DOESN'T COMPILE
          Comparator c3 = (Object a, Integer b) -> 1;           //DOESN'T COMPILE
          Comparator c4 = (Integer a, Integer b) -> 1;          //DOESN'T COMPILE   
          Comparator<Integer> c4 = (Integer a, Integer b) -> 1; //OK
Of course these are not the same as method references; they are just easier for me to type than multiple methods but still:

Code: Select all

    Comparator c5 = T23::fooA;              //DOESN'T COMPILE
    Comparator c6 = T23::fooB;              //DOESN'T COMPILE
    Comparator<Double> c7 = T23::fooB;      //OK
    static int fooA(int a, int b) { return 0; }
    static int fooB(Double d, Double d2) { return 0; }

Re: About Question enthuware.ocpjp.v8.2.1792 :

Posted: Mon Aug 12, 2019 12:56 pm
by sir_Anduin@yahoo.de
I think the max method needs some kind of sorter. And when sorted, it takes the first (or last) element in the list. Of cource sorting with Integer::max does not work, as it does not fulfill the Comparator.compare contract:
which is defined to return one of -1, 0, or 1 according to whether the value of expression is negative, zero or positive.
from
https://docs.oracle.com/javase/8/docs/a ... re(T,%20T)

Re: About Question enthuware.ocpjp.v8.2.1792 :

Posted: Sun Sep 01, 2019 9:35 am
by tylrdr
lucian wrote:
Mon Oct 03, 2016 9:31 am
Maybe this will make understanding easier the difference between Integer.max() and Integer.compare() methods usage in a stream max method

Code: Select all

        System.out.println("USING Integer.max()");
        System.out.println(ls.stream().max((o1, o2) -> {System.out.print(o1);
                                                        System.out.print(o2);
                                                        int max = Integer.max(o1, o2);
                                                        System.out.print(max);
                                                        System.out.print("\t");
                                                        return max;})
                                      .get());
        System.out.println("USING Integer.compare()");
        System.out.println(ls.stream().max((o1, o2) -> {System.out.print(o1);
                                                        System.out.print(o2);
                                                        int max = Integer.compare(o1, o2);
                                                        System.out.print(max);
                                                        System.out.print("\t");
                                                        return max;})
                                      .get());

Code: Select all

USING Integer.max()
344	366	399	323	355	377	3
USING Integer.compare()
34-1	46-1	69-1	921	951	971	9
I added some comments to your excellent code for my own understanding. Thank you sir! Maybe someone finds my comments useful when understanding this question)

https://paste.ee/p/EiT6L

Re: About Question enthuware.ocpjp.v8.2.1792 :

Posted: Tue Dec 03, 2019 8:54 am
by Bhaskar
I would like to add my explanation/understanding to all the excellent answers above.
The confusion for me came specifically from the fact that Integer.max() always returns the largest value as opposed to Integer.compare() method, that returns the difference between the comparing values.

For example:

Code: Select all

List<Integer> ls = Arrays.asList(-1, 4, 6);
System.out.println(ls.stream().max((x, y) -> {
            System.out.println(x + " " + y);
            System.out.println("max: " + Integer.max(x, y));
            System.out.println("");
            return Integer.max(x, y);
        }).get());
o/p:
-1 4
max: 4

-1 6
max: 6

-1

Although at each iteration in Comparator the maximum value is clearly defined, the stream().max() method sees the values in terms of +ve, -ve or 0.
Therefore, max(-1, 4) returns a positive value (i.e. 4) and stream().max() method thinks that -1 is greater than 4 and uses it for further comparisons. For more clarity, look at the following example:

Code: Select all

List<Integer> ls = Arrays.asList(-1, 4, -2, 6);
        System.out.println(ls.stream().max((x, y) -> {
            System.out.println(x + " " + y);
            System.out.println("max: " + Integer.max(x, y));
            System.out.println("");
            return Integer.max(x, y);
        }).get());
o/p:
-1 4
max: 4

-1 -2
max: -1

-2 6
max: 6

-2

In contrast, Integer.compare() checks the adjacent values and works similarly as calling Comparable interface's compareTo method.

Please feel free to correct me if I'm wrong.

Re: About Question enthuware.ocpjp.v8.2.1792 :

Posted: Tue Dec 03, 2019 8:51 pm
by admin
Stream's max(Comparator c) expects a Comparator. A Comparator's contract is given in its API JavaDoc:
Compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
So, yes, if you use Integer.max to build a Comparator for Stream's max, it will give weird results as your example shows.