Java排序报错Comparison method violates its general contract原因及修复咨询
报错原因
- 第一处笔误:
getCompare方法中计算indexRight时,错误使用leftId判断是否存在于map中,导致indexRight的取值逻辑完全错误。 - 第二处违反Comparator契约:只要任意一个元素的id不在
orderMap中就固定返回1,违背了比较器的核心对称性要求:对任意a、b,sgn(compare(a,b))必须等于-sgn(compare(b,a))。举例说明:如果a的id不在map中、b的id在map中,调用compare(a,b)返回1,调用compare(b,a)时也会触发「任意一个值小于0就返回1」的逻辑,同样返回1,正负号不相反,直接触发JDK的排序契约校验报错。
修复方案
首先修正indexRight的取值笔误,再补全不在map中元素的比较逻辑,可根据业务需要把不在map中的元素统一放到排序结果的头部或尾部,保证比较逻辑的对称性。
示例代码(不在map中的元素默认放到排序末尾):
private int getCompare(Map<Long, Integer> orderMap, Long leftId, Long rightId) { // 修正indexRight的判断逻辑,改用rightId判断存在性,用getOrDefault简化代码 int indexLeft = orderMap.getOrDefault(leftId, -1); int indexRight = orderMap.getOrDefault(rightId, -1); // 两个都不在map里,认为相等 if (indexLeft < 0 && indexRight < 0) { return 0; } // 只有left不在,left排在后面 if (indexLeft < 0) { return 1; } // 只有right不在,right排在后面 if (indexRight < 0) { return -1; } // 都在map里,按预设index排序 return Integer.compare(indexLeft, indexRight); }
如果需要把不在map中的元素放到排序最前面,把上述代码中返回1和-1的位置互换即可。
内容的提问来源于stack exchange,提问作者kk jj
相关产品推荐
相关产品推荐

