Let's say I have a Pair class
public class Pair<P, Q> {
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<Pair<Integer, Integer>> 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<P,Q> 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.<Integer, Integer>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 compare MethodIt returns a positive value if obj1 is greater than obj2. Otherwise, a negative value is returned. By overriding compare( ), you can alter the way that objects are ordered. For example, to sort in a reverse order, you can create a comparator that reverses the outcome of a comparison.
A ComparatorChain evaluates every Comparator in the chain as needed. If the current Comparator returns a zero, the next Comparator is invoked until there are no more Comparator objects left in the chain. If the final Comparator returns a zero value, the ComparatorChain returns a zero.
It should be:
pairList.sort(Comparator.<Pair, Integer>comparing(Pair::firstValue)
.thenComparing(Pair::secondValue));
First type parameter refers to the type being passed to Comparator. Second type parameter refers to the type that comparator should effectively compare with.
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.<Pair>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));
// ^^^^^
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With