How does Java know which String::compareTo
method reference to use when calling Collections.sort(someListOfStrings, String::compareTo);
? compareTo
is not static and it needs to know the value
of the "left hand side" of the comparison.
Asked
Active
Viewed 3,143 times
10

stantonk
- 1,922
- 1
- 18
- 24
-
what is this `String::compareTo` – diyoda_ Sep 05 '15 at 23:10
-
Your question is not clear: `Collections.sort` sorts the items of a collection, `String::compareTo` is used to compare two strings in that collection. if string a < string b then by doing `a.compareTo(b)` you'll get a negative result and `b.compareTo(a)` will return a positive result, either way - this result will be used to sort the items properly. – Nir Alfasi Sep 05 '15 at 23:11
-
More detail here - https://stackoverflow.com/q/35914775/3333878 – abitcode Mar 19 '20 at 11:49
2 Answers
15
Suppose that you use method reference for Comparator
interface:
Comparator<String> cmp = String::compareTo;
When you call the cmp.compare(left, right)
(which is "single abstract method" or "SAM" of Comparator
interface), the magic occurs:
int result = cmp.compare(left, right);
| |
/------------------------/ |
| /---------------/
| |
left.compareTo(right);
Basically all the parameters of SAM are converted to the parameters of the referred method, but this
object (which is on the left side) is also counted as parameter.

Tagir Valeev
- 97,161
- 19
- 222
- 334
-
8
-
@Tagir Valeev but how does `String::compareTo`'s type match `Comparator
`? The type signature doesn't match... `String`'s `compareTo` method is `public int compareTo(String anotherString)`, `Comparator – stantonk Sep 06 '15 at 21:06` is ` int compare(String o1, String o2);` I know I'm missing something I cant quite connect the dots. -
2@stantonk, think about `this` as about one more parameter, so `public int compareTo(String anotherString)` is like `public static int compareTo(String this, String anotherString)`. Generally in OOP-languages internally it works like this: the object pointer (reference) is converted to the first parameter of the function/method. – Tagir Valeev Sep 07 '15 at 01:05
-
@TagirValeev A HAH! Yes yes, it makes sense now. Python makes this explicit in instance method signatures by always requiring `self` as the first parameter. It would have to be an implied parameter, since methods have to be bound somehow to the appropriate instance for them to be methods on a class instance and know to which `this` one was referring. Thanks! – stantonk Sep 07 '15 at 04:20
-
@stantonk: note that Java 8 allows you to declare the `this` instance explicitly, if you prefer that, like `ReturnType instancemethod(MyType this, OtherParameterType arg1, …)` – Holger Sep 25 '15 at 15:26
0
OK, the source of Collections.sort() looks as follows:
public static <T> void sort(List<T> list, Comparator<? super T> c) {
Object[] a = list.toArray();
Arrays.sort(a, (Comparator)c);
ListIterator i = list.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set(a[j]);
}
}
I think it is quite clear now. The contents is a list. It means it has an order and the items are treated one by one in that order.

TomS
- 1,159
- 2
- 17
- 35
-
sorry, that does not answer my question. What I'm trying to understand is how Java knows to use the correct `String::compareTo` method reference for each element in the list to be sorted. – stantonk Sep 06 '15 at 01:28
-
so, for instance, let's say you had a list `["c", "b", "a"]`. the first element in that list, "c", is an instance of the `String` class, which has a property of `value` that is a character array containing a single character, 'c'. `compareTo` makes a comparison between "c" and "b" deep inside the `Collections.sort` method, i.e. `if (c.compare(a[runHi++], a[lo]) < 0) `. I am not seeing how the method reference gets you from `Comparable` to `Comparator`. – stantonk Sep 06 '15 at 01:35