Issue with Comparator.comparing

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Fri Dec 14 15:28:27 UTC 2018


I get that there are other ways to make the example working. But the API 
says:

"Accepts a function that extracts a |Comparable| 
<https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html> 
sort key from a type |T|, and returns a |Comparator<T>| that compares by 
that sort key."

There's no other note in the API which hints at the fact that it might 
spectacularly fail because of heap pollution. And the fact that it is a 
synthetic cast that is failing, is strongly hinting at something at odds 
with the type-system.

Maurizio


On 14/12/2018 13:52, B. Blaser wrote:
> 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);
>      }
> }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20181214/46e89f32/attachment.html>


More information about the compiler-dev mailing list