Let's say I have a Pair class
public class Pair
{
public P p;
public Q q;
public Pair(P p, Q q) {
this.p = p;
this.q = q;
}
public int firstValue() {
return ((Number)p).intValue();
}
public int secondValue() {
return ((Number)q).intValue();
}
}
And I wish to sort it, first by first value, then by second value. Now' if I do this
List> pairList = new ArrayList<>();
pairList.add(new Pair<>(1, 5));
pairList.add(new Pair<>(2, 2));
pairList.add(new Pair<>(2, 22));
pairList.add(new Pair<>(1, 22));
pairList.sort(Comparator.comparing(Pair::firstValue));
Everything works well and good, the list is sorted by first values of pair, but if I do this
pairList.sort(Comparator.comparing(Pair::firstValue).thenComparing(Pair::secondValue));
It fails with error
Error:(24, 38) java: incompatible types: cannot infer type-variable(s) T,U
(argument mismatch; invalid method reference
method firstValue in class DataStructures.Pair
cannot be applied to given types
required: no arguments
found: java.lang.Object
reason: actual and formal argument lists differ in length)
Ok,so it might not be able to infer the arguments, so if I do this
pairList.sort(Comparator.comparing(Pair::firstValue)
.thenComparing(Pair::secondValue));
It fails with error
Error:(24, 39) java: invalid method reference
non-static method firstValue() cannot be referenced from a static context
Why does it work for comparing() and not for comparing().thenComparing() ?
解决方案
The error seems to be related to Pair's generic parameters. One workaround it to use an explicit type, as you've attempted:
pairList.sort(Comparator.comparingInt(Pair::firstValue).thenComparingInt(Pair::secondValue));
// ^^^^^^
Note the comparingInt() which reduces the number of parameters you need to specify, and improves performance by avoiding boxing.
Another solution is to parameterize the type reference:
pairList.sort(Comparator.comparingInt(Pair,?>::firstValue).thenComparingInt(Pair::secondValue));
// ^^^^^