java - Unable to replicate : "Comparison method violates its general contract!" -
i receive following error: "comparison method violates general contract!" when using following comparator, unable replicate exception using junit. i'd know caused issue , how replicate it. there examples of others having same problem not how replicate it.
public class dtocomparator implements comparator<dto> { @override public int compare(dto r1, dto r2) { int value = 0; value = r1.getorder() - r2.getorder(); if (value == 0 && !isvaluenull(r1.getdate(), r2.getdate())) value = r1.getdate().compareto(r2.getdate()); return value; } private boolean isvaluenull(date date, date date2) { return date == null || date2 == null; } }
the code called using:
collections.sort(dtos, new dtocomparator());
thanks help.
extra info: error seemed occur in timsort class inside java utils , within method called mergelo. link: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/util/timsort.java#timsort.mergelo%28int%2cint%2cint%2cint%29
from documentation of compare
.
the implementor must ensure
sgn(x.compareto(y)) == -sgn(y.compareto(x))
x
,y
subtraction-based comparators not meet condition. because subtraction can overflow. example
integer.min_value - 0 0 - integer.min_value
are both negative.
there problem way have dealt date
s. documentation of compare
:
finally, implementor must ensure
x.compareto(y)==0
impliessgn(x.compareto(z)) == sgn(y.compareto(z))
,z
.
your compare
method breaks this. example, if x
null
, y
january 1st 1970 , z
january 2nd 1970, then
compare(x, y) == 0 // x == null compare(x, z) == 0 // x == null compare(y, z) == -1 // january 1st before january 2nd.
i write method follows:
@override public int compare(dto r1, dto r2) { int value = integer.compare(r1.getorder(), r2.getorder()); if (value != 0) return value; date date1 = r1.getdate(); date date2 = r2.getdate(); if (date1 == null && date2 == null) return 0; if (date1 == null) return -1; if (date2 == null) return 1; return date1.compareto(date2); }
i have managed reproduce problem, list
s of length @ least 32
. see link explanation of why list
of size @ least 32
required. why program using collections.sort fail lists of size 32 or more?
public class main { private static final class numanddate { private final int num; private final date date; numanddate(int num, date date) { this.num = num; this.date = date; } } public static final class numanddatecomparator implements comparator<numanddate> { @override public int compare(numanddate r1, numanddate r2) { int value = 0; value = r1.num - r2.num; if (value == 0 && !isvaluenull(r1.date, r2.date)) value = r1.date.compareto(r2.date); return value; } private boolean isvaluenull(date date, date date2) { return date == null || date2 == null; } } public static void main(string[] args) { numanddate[] array = { new numanddate(0, new date(0)), new numanddate(0, new date(1)), new numanddate(0, null) }; random random = new random(); (int = 0; < 100; i++) { (int j = 0; j < 10000; j++) { list<numanddate> list = new arraylist<>(); int[] arr = new int[i]; (int k = 0; k < i; k++) { int rand = random.nextint(3); arr[k] = rand; list.add(array[rand]); } try { collections.sort(list, new numanddatecomparator()); } catch (exception e) { system.out.println(arr.length + " " + arrays.tostring(arr)); return; } } } } }
Comments
Post a Comment