-1

What exactly does the following overload of Collections.sort():

sort(List<T> list, Comparator<? super T> c)

ask for as the second argument?


Example: I initiate a list of 7 random integers as:

List<Integer> listOfInts = new ArrayList<>();
Random rand = new Random(System.currentTimeMillis());
for (int i = 0; i < 7; i++) {
    listOfInts.add(rand.nextInt());
}

Then I try to sort them using Collections.sort() as:

Collections.sort(listOfInts, Integer :: compare);

as well as:

Collections.sort(listOfInts, Integer :: compareTo);

and they both work. Why doesn't the call to sort the collection using compareTo() throw/fail? The signature of compareTo() is totally different from the signature of compare().

displayName
  • 13,888
  • 8
  • 60
  • 75
  • http://stackoverflow.com/questions/420223/what-is-the-difference-between-compare-and-compareto – msadler Mar 14 '16 at 01:50
  • I think you are getting slightly confused by lambdas introduced in Java 8. Try that in Java 7 and you will be able to easily see it. – Jaroslaw Pawlak Mar 14 '16 at 01:52
  • @msadler: Methods giving same answer is different from methods being the same. `compare` compares two things while `compareTo` is called on the instance of one thing to compare it with another. I'm mentioning it in the last line of my question already. Anyways, thanks for linking this answer here. I read it before posting this question but its good to have it linked. – displayName Mar 14 '16 at 01:52
  • @JaroslawPawlak: You are absolutely right, the culprit is lambdas. But I wish to understand the concept in light of lambdas. Otherwise this question doesn't arise in the first place, for me. – displayName Mar 14 '16 at 01:54
  • Sorry but I don't understand why you expect it to fail. And the exact term is 'type inference', not lambdas. – Rahul Sharma Mar 14 '16 at 01:57
  • @RahulSharma: I don't expect it to fail per se, but I don't get how it works! The way I see, the two methods being passed are quite different. – displayName Mar 14 '16 at 02:00
  • Check [this](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/lang/Integer.java#Integer.compareTo%28java.lang.Integer%29) out. The implementation of compareTo is just a call to the static compare method, therefore the results for the two methods are the same. Hope this helps. – Rahul Sharma Mar 14 '16 at 02:08
  • @RahulSharma: Even if its just a wrapper over the same method, the call is different. I think I'm not yet precisely able to understand my problem. There's something that lambdas do that I don't know of. – displayName Mar 14 '16 at 02:10

2 Answers2

2

You're using two types of method references. The first is a reference to a static method. The second is a reference to a type instance method. After autoboxing, they both share the same functional signature of (Integer, Integer) -> int.

Since method references are just syntactical sugar for lambdas, here's how they would translate into lambdas:

Integer::compare evaluates to

(int left, int right) -> Integer.compare(left, right)

Integer::compareTo evaluates to

(Integer left, Integer right) -> left.compareTo(right)
shmosel
  • 49,289
  • 6
  • 73
  • 138
  • Your answer clarifies the point partly. I don't understand how can two methods having different signature be accepted to produce same effect on the data? Will read autoboxing before commenting further on your answer. – displayName Mar 14 '16 at 02:01
  • Wish I could up-vote twice. Thank you for your explanation. Your answer makes it clear. – displayName Mar 14 '16 at 03:12
1
Collections.sort(listOfInts, Integer::compare);

is equivalent to this code in older Java:

Collections.sort(list, new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return Integer.compare(o1, o2);
    }
});

While

Collections.sort(listOfInts, Integer::compareTo);

is equivalent to

Collections.sort(list, new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o1.compareTo(o2);
    }
});

There is no overloading here. sort method requires the second argument to be a Comparator. It is just Java 8 lambdas that hide it from you.

Jaroslaw Pawlak
  • 5,538
  • 7
  • 30
  • 57
  • Your answer makes sense to me. If possible for you, could you elaborate how the lambdas *actually* hide it? No prob if you can't. – displayName Mar 14 '16 at 02:03
  • @displayName They hide it exactly as shown above. You type `Integer::compare` but it actually creates a `new Comparator()` whose `compareTo(Integer o1, Integer o2)` method's implementation is `return Integer.compare(o1, o2);` – Jaroslaw Pawlak Mar 14 '16 at 02:20