Issue with Comparator.comparing
B. Blaser
bsrbnd at gmail.com
Fri Dec 14 13:52:49 UTC 2018
On Thu, 13 Dec 2018 at 14:52, B. Blaser <bsrbnd at gmail.com> wrote:
>
> On Thu, 13 Dec 2018 at 13:30, Maurizio Cimadamore
> <maurizio.cimadamore at oracle.com> wrote:
> >
> > [...]
> >
> > Concluding, I really believe that the capture conversion introduced by
> > JDK-8029307, which was kind of a forced move (to type check a method
> > reference you have to reason about membership, which implies capture of
> > the receiver), is messing things up here, because, from a type system
> > perspective, it makes it look as if all possible calls to the functional
> > interface derived from that method reference is _always_ going to yield
> > the _same_ captured type, where in reality different captures will be
> > emitted. This is what made me think that this is indeed a type system
> > issue, very close (if not the same) to the one described in JDK-8170887.
>
> At my mind, the problem is more within 'Comparator::comparing' which
> assumes that the key extractor is the same for both elements
> concluding that 'compareTo' should be applicable.
> So, I think It might be more an API design concern than a type system
> issue, but I understand your position.
Explicitly, what I meant is that you'd have to provide a custom
'keyComparator' to sort an heterogeneous collection, as below.
Did I miss anything in your original example that would suggest a type
system issue rather than an API misuse?
Bernard
import java.util.*;
import java.util.stream.*;
import java.util.function.*;
class Foo2<T extends Comparable<T>> {
static Foo2<String> S = new Foo2<>("");
static Foo2<Integer> I = new Foo2<>(42);
static Foo2<Integer> J = new Foo2<>(41);
private T t;
Foo2(T t) {
this.t = t;
}
T t() {
return t;
}
static int keyComp(Comparable<?> t1, Comparable<?> t2) {
if (t1 instanceof Integer && t2 instanceof Integer)
return (Integer)t1 - (Integer)t2;
else
return t1.getClass().hashCode() - t2.getClass().hashCode();
}
public static void main(String[] args) {
List<Foo2<?>> l = new ArrayList<>();
l.add(S);
l.add(I);
l.add(J);
Comparator<Comparable<?>> kc = Foo2::keyComp;
Comparator<? super Foo2<?>> comp = Comparator.comparing(Foo2::t, kc);
Collections.sort(l, comp);
for (Foo2<?> f: l)
System.out.println(f.t);
}
}
More information about the compiler-dev
mailing list