排序时出现Comparison method violates its general contract!错误求助
搞定「Comparison method violates its general contract!」报错
兄弟,这个报错是因为你的比较器逻辑违反了Java Comparator必须遵守的通用规则(自反性、对称性、传递性),咱们来捋清楚问题出在哪,以及怎么修复:
为啥会报错?
你代码里用了Math.round(StudentName1 - StudentName2)来返回比较结果,这简直是踩了比较器的大坑!举个例子你就懂了:
假设三个酒店的评分分别是3.3、3.6、3.9:
- 3.3和3.6的差是-0.3,round后是0 → 你代码会认为这俩评分相等
- 3.6和3.9的差是-0.3,round后也是0 → 同样认为相等
- 但3.3和3.9的差是-0.6,round后是-1 → 认为3.3小于3.9
这就违反了传递性规则:如果a等于b,b等于c,那a必须等于c,但这里a却小于c,Java的排序算法直接就炸了,抛出那个报错。
另外吐槽下,你的变量名起得太离谱了——StudentName1居然存的是酒店评分,这以后维护代码的人得骂街😂,建议改成rating1这种一目了然的名字。
正确的修复方案
给你两个靠谱的解法,随便选一个都能解决问题:
方案1:用Double自带的compareTo(最推荐)
Double类本身就实现了正确的比较逻辑,直接用就行,完全符合规则:
public static Comparator<HotelResult> HotelLowRatingComparator = new Comparator<HotelResult>() { public int compare(HotelResult s1, HotelResult s2) { Double rating1 = Double.valueOf(s1.getStarRating()); Double rating2 = Double.valueOf(s2.getStarRating()); // 升序排序,直接返回比较结果 return rating1.compareTo(rating2); } };
方案2:手动判断差值(避免自动装箱的话用这个)
如果不想用Double的包装类,直接用基本类型手动判断也很稳妥:
public static Comparator<HotelResult> HotelLowRatingComparator = new Comparator<HotelResult>() { public int compare(HotelResult s1, HotelResult s2) { double rating1 = s1.getStarRating(); double rating2 = s2.getStarRating(); if (rating1 < rating2) { return -1; } else if (rating1 > rating2) { return 1; } else { return 0; } } };
最后再提个醒
以后别再用(int)(a - b)或者Math.round(a - b)来做比较了!浮点数的精度问题加上round的特性,很容易破坏比较器的规则,就算Java老版本不报错,排序结果也会乱得一塌糊涂。
内容的提问来源于stack exchange,提问作者Seetha
相关产品推荐
相关产品推荐

