-
Bug
-
Resolution: Fixed
-
P4
-
8, 9
-
b36
-
Verified
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 ----------
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 ----------