Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8171826

Comparator.reverseOrder(c) mishandles singleton comparators

XMLWordPrintable

      FULL PRODUCT VERSION :
      java version "1.8.0_77"
      Java(TM) SE Runtime Environment (build 1.8.0_77-b03)
      Java HotSpot(TM) 64-Bit Server VM (build 25.77-b03, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Darwin retina.dellroad.org 16.1.0 Darwin Kernel Version 16.1.0: Wed Oct 19 20:31:56 PDT 2016; root:xnu-3789.21.4~4/RELEASE_X86_64 x86_64 i386 MacBookPro10,1 Darwin


      A DESCRIPTION OF THE PROBLEM :
      Collections.reverseOrder() and Comparator.reverseOrder() should use the same non-public classes.

      Instead, they are using different classes. This causes the returned Comparators to not be equals() to each other when they should be.

      This is a problem because in some applications certain optimizations are possible when equal comparators can be detected, for example, when calculating the intersection of two NavigableSets.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile and run the test case.


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      No output
      ACTUAL -
      Comparator.naturalOrder() AND Comparator.reverseOrder().reversed() are NOT EQUAL
      Comparator.naturalOrder() AND Collections.reverseOrder().reversed() are NOT EQUAL
      Comparator.naturalOrder() AND Collections.reverseOrder(Comparator.reverseOrder()) are NOT EQUAL
      Comparator.reverseOrder() AND Comparator.naturalOrder().reversed() are NOT EQUAL
      Comparator.reverseOrder() AND Collections.reverseOrder() are NOT EQUAL
      Comparator.reverseOrder() AND Collections.reverseOrder(Comparator.naturalOrder()) are NOT EQUAL
      Comparator.naturalOrder().reversed() AND Collections.reverseOrder() are NOT EQUAL
      Comparator.naturalOrder().reversed() AND Collections.reverseOrder(Comparator.naturalOrder()) are NOT EQUAL
      Comparator.reverseOrder().reversed() AND Collections.reverseOrder().reversed() are NOT EQUAL
      Comparator.reverseOrder().reversed() AND Collections.reverseOrder(Comparator.reverseOrder()) are NOT EQUAL
      Collections.reverseOrder() AND Collections.reverseOrder(Comparator.naturalOrder()) are NOT EQUAL
      Collections.reverseOrder().reversed() AND Collections.reverseOrder(Comparator.reverseOrder()) are NOT EQUAL


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.util.*;
      public class xx {
          public static void main(String[] args) throws Exception {

              final Example[] examples = new Example[] {
                  new Example("Comparator.naturalOrder()", Comparator.<Byte>naturalOrder(), false),
                  new Example("Comparator.reverseOrder()", Comparator.<Byte>reverseOrder(), true),
                  new Example("Comparator.naturalOrder().reversed()", Comparator.<Byte>naturalOrder().reversed(), true),
                  new Example("Comparator.reverseOrder().reversed()", Comparator.<Byte>reverseOrder().reversed(), false),

                  new Example("Collections.reverseOrder()", Collections.<Byte>reverseOrder(), true),
                  new Example("Collections.reverseOrder().reversed()", Collections.<Byte>reverseOrder().reversed(), false),

                  new Example("Collections.reverseOrder(Comparator.naturalOrder())", Collections.<Byte>reverseOrder(Comparator.<Byte>naturalOrder()), true),
                  new Example("Collections.reverseOrder(Comparator.reverseOrder())", Collections.<Byte>reverseOrder(Comparator.<Byte>reverseOrder()), false),
              };

              for (int i = 0; i < examples.length; i++) {
                  final Example a = examples[i];
                  for (int j = i + 1; j < examples.length; j++) {
                      final Example b = examples[j];
                      if (a.reverse == b.reverse && !a.equals(b))
                          System.out.println(a.name + " AND " + b.name + " are NOT EQUAL");
                  }
              }
          }

          public static class Example {
              public final String name;
              public final Comparator<Byte> c;
              public final boolean reverse;
              Example(String name, Comparator<Byte> c, boolean reverse) {
                  this.name = name;
                  this.c = c;
                  this.reverse = reverse;
              }
          }
      }

      ---------- END SOURCE ----------

            psandoz Paul Sandoz
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated:
              Resolved: