Comparison method violates its general contract while comparing java.util.Date -
i getting error below:
caused by: javax.faces.el.evaluationexception: java.lang.illegalargumentexception: comparison method violates general contract! @ javax.faces.component.methodbindingmethodexpressionadapter.invoke(methodbindingmethodexpressionadapter.java:101) [jboss-jsf-api_2.1_spec-2.1.28.sp1-redhat-1.jar:2.1.28.sp1-redhat-1] @ com.sun.faces.application.actionlistenerimpl.processaction(actionlistenerimpl.java:101) [jsf-impl-2.1.28.redhat-10.jar:2.1.28.redhat-10] @ javax.faces.component.uicommand.broadcast(uicommand.java:315) [jboss-jsf-api_2.1_spec-2.1.28.sp1-redhat-1.jar:2.1.28.sp1-redhat-1] @ javax.faces.component.uiviewroot.broadcastevents(uiviewroot.java:786) [jboss-jsf-api_2.1_spec-2.1.28.sp1-redhat-1.jar:2.1.28.sp1-redhat-1] @ javax.faces.component.uiviewroot.processapplication(uiviewroot.java:1251) [jboss-jsf-api_2.1_spec-2.1.28.sp1-redhat-1.jar:2.1.28.sp1-redhat-1] @ com.sun.faces.lifecycle.invokeapplicationphase.execute(invokeapplicationphase.java:81) [jsf-impl-2.1.28.redhat-10.jar:2.1.28.redhat-10] @ com.sun.faces.lifecycle.phase.dophase(phase.java:101) [jsf-impl-2.1.28.redhat-10.jar:2.1.28.redhat-10] @ com.sun.faces.lifecycle.lifecycleimpl.execute(lifecycleimpl.java:118) [jsf-impl-2.1.28.redhat-10.jar:2.1.28.redhat-10] @ javax.faces.webapp.facesservlet.service(facesservlet.java:593) [jboss-jsf-api_2.1_spec-2.1.28.sp1-redhat-1.jar:2.1.28.sp1-redhat-1] ... 29 more caused by: java.lang.illegalargumentexception: comparison method violates general contract! @ java.util.timsort.mergehi(timsort.java:899) [rt.jar:1.8.0_65] @ java.util.timsort.mergeat(timsort.java:516) [rt.jar:1.8.0_65] @ java.util.timsort.mergeforcecollapse(timsort.java:457) [rt.jar:1.8.0_65] @ java.util.timsort.sort(timsort.java:254) [rt.jar:1.8.0_65] @ java.util.arrays.sort(arrays.java:1512) [rt.jar:1.8.0_65] @ java.util.arraylist.sort(arraylist.java:1454) [rt.jar:1.8.0_65] @ java.util.collections.sort(collections.java:175) [rt.jar:1.8.0_65]
below code compare method. vo1.getattribute()
returns java.util.date
object.
@override public int compare(datecomparablevo vo1, datecomparablevo vo2) { if (vo1 != null && vo1.getattribute() != null && vo2 != null && vo2.getattribute() != null) { return vo1.getattribute().compareto(vo2.getattribute()); } return -1; }
is there wrong implementation of compare method?
in case of null scenario.
why below code works without issue.
package test; import java.util.arraylist; import java.util.collections; import java.util.comparator; import java.util.date; import java.util.list; public class testmain { public static void main(string[] args) { list<employee> employees = new arraylist<employee>(); employees.add(new employee(new date())); employees.add(null); employees.add(new employee(new date())); employees.add(new employee(new date())); employees.add(null); employees.add(new employee(new date())); employees.add(null); system.out.println(employees.size()); collections.sort(employees, new employeecomparator()); } } class employee { private date attribute; public employee() { // todo auto-generated constructor stub } public employee(date attribute) { this.attribute = attribute; } public date getattribute() { return attribute; } public void setattribute(date attribute) { this.attribute = attribute; } @override public string tostring() { return "employee [attribute=" + attribute + "]"; } } class employeecomparator implements comparator<employee>{ @override public int compare(employee vo1, employee vo2) { system.out.println("vo1 : " + vo1 + " vo2 : " + vo2); if (vo1 != null && vo1.getattribute() != null && vo2 != null && vo2.getattribute() != null) { return vo1.getattribute().compareto(vo2.getattribute()); } return -1; } }
output
7 vo1 : null vo2 : employee [attribute=fri aug 18 11:51:11 sgt 2017] vo1 : employee [attribute=fri aug 18 11:51:11 sgt 2017] vo2 : null vo1 : employee [attribute=fri aug 18 11:51:11 sgt 2017] vo2 : employee [attribute=fri aug 18 11:51:11 sgt 2017] vo1 : employee [attribute=fri aug 18 11:51:11 sgt 2017] vo2 : null vo1 : employee [attribute=fri aug 18 11:51:11 sgt 2017] vo2 : employee [attribute=fri aug 18 11:51:11 sgt 2017] vo1 : null vo2 : null vo1 : null vo2 : employee [attribute=fri aug 18 11:51:11 sgt 2017] vo1 : null vo2 : employee [attribute=fri aug 18 11:51:11 sgt 2017] vo1 : employee [attribute=fri aug 18 11:51:11 sgt 2017] vo2 : employee [attribute=fri aug 18 11:51:11 sgt 2017] vo1 : employee [attribute=fri aug 18 11:51:11 sgt 2017] vo2 : employee [attribute=fri aug 18 11:51:11 sgt 2017] vo1 : null vo2 : null vo1 : null vo2 : employee [attribute=fri aug 18 11:51:11 sgt 2017] vo1 : null vo2 : null
am missing important part in understanding compare
the "contract" comparison comparison function has define total order. 1 of requirements of total order "asymmetry", means if < b, b > a. in java terms, means if compare(a,b)
(or a.compareto(b)
) returns result < 0, compare(b,a)
(or b.compareto(a)
) must return result > 0. comparison function doesn't obey rule; if x.getattribute()
non-null , y.getattribute()
null, compare(x,y)
returns -1 , compare(y,x)
returns -1. timsort notices , throws exception when spots comparison doesn't return expects.
another way @ it: have decide beforehand order want things in if there "special" values in input (except if want objects compare "equal", order doesn't matter). suppose input contains objects getattribute()
null, , objects getattribute()
non-null. want ones null attribute appear in output? how want them ordered? "i don't care" not option. let's want null-attribute ones come last, don't care how null-attribute objects ordered. need write comparison function that
- an object non-null attribute < object null attribute;
- an object null attribute > object non-null attribute;
- two object null attributes treated equal (comparison function returns 0).
if want null ones appear first in array, < , > in first 2 points reversed. if want 2 objects null attributes ordered based on other attribute, write comparison function that, you'll still need decide ones null attribute appear relative ones non-null attribute. maybe doesn't matter 1 choose. have choose something, , have write comparison function return result based on you've chosen.
p.s.: there's no particular reason why second code snippet employee
works , first 1 doesn't. comparator in second case wrong in first one. however, timsort doesn't @ every pair of elements make sure comparison meets contract (that make o(n2) algorithm). i'm not familiar details of timsort, suspect makes check when has reason compare 2 elements see if comparison (perhaps) <0 or =0, , "knows" >0 should not possible if comparison function meets contract. it's pretty cheap check result >0 if has make comparison, doubt timsort calls comparators when doesn't have to, since execution time of comparator beyond control. basic reason second example works "you got lucky".
Comments
Post a Comment