Java排序方法报错Comparison method violates its general contract求助
错误原因
- 第一是存在低级语法错误:代码中多处
getClass后缺少方法调用括号(),比如o2.getClass、o1.getClass都要修正为getClass()才能正常执行。 - 核心逻辑错误是你的自定义比较器违反了Java
Comparator的强制约定:Java要求比较器必须满足对称性、传递性、自反性,否则在JDK7及以上版本排序时就会抛出Comparison method violates its general contract异常。
你的现有逻辑如果列表中出现RandomObject除someClass1、someClass2之外的其他子类实例,就会出现对称冲突:比如C类和someClass1比较返回1,someClass1和C类比较也返回1,完全违反对称性要求。就算列表中只有这两个类的实例,也建议用更稳妥的优先级映射写法避免边界问题。 - 额外隐含风险:如果
getName()返回null,调用compareTo时会直接抛出空指针异常。
修复代码
如果你的列表仅包含someClass1、someClass2两个子类的实例,可用如下修复后的代码:
List<RandomObject> list; list.stream().sorted((o1, o2) -> { // 先比较类型优先级 boolean o1IsType1 = o1.getClass() == someClass1.class; boolean o2IsType1 = o2.getClass() == someClass1.class; if (o1IsType1 != o2IsType1) { // someClass1排在前面,所以o1是someClass1、o2不是的话返回-1 return o1IsType1 ? -1 : 1; } // 同类型按name排序,这里加null判断更稳妥,不需要可以删掉 String name1 = o1.getName() == null ? "" : o1.getName(); String name2 = o2.getName() == null ? "" : o2.getName(); return name1.compareTo(name2); })
如果后续可能新增其他子类,建议给所有子类定义固定优先级数值,先比优先级再比name,逻辑更严谨不会违反比较约定。
内容的提问来源于stack exchange,提问作者HolyFreak2
相关产品推荐
相关产品推荐

