首先,我们需要了解一下“Comparison method violates its general contract”异常的意义。这个异常意味着我们在使用Java排序方法时,按照给定的比较器进行比较时违反了排序的基本规则,可能会导致排序结果出现异常,或者在使用Collections.sort()等排序方法时,发生无限递归的错误。
因此,当我们遇到这种异常时,我们需要检查我们的比较器是否遵循以下三个规则:
-
反射性:对于任何非 null 的引用值 x,都有 x.equals(x) 返回 true。
-
对称性:对于任何非 null 的引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才返回 true。
-
传递性:对于任何非 null 的引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 也应该返回 true。
接下来,我们将提供两个示例说明如何解决这个问题。
示例一:
假设我们有一个Person类,该类包含id、name、age属性,我们希望根据id进行排序。我们提供以下比较器:
Comparator<Person> comparator = Comparator.comparing(Person::getId);
Collections.sort(personList, comparator);
但是,如果我们将两个Person实例视为相等,并且将它们与一个新的空实例进行比较,则会违反传递性规则。因此,我们需要在比较器中添加一个null值检查:
Comparator<Person> comparator = Comparator.comparing(Person::getId,
Comparator.nullsFirst(Integer::compareTo));
Collections.sort(personList, comparator);
这样,我们就可以避免“Comparison method violates its general contract”异常。
示例二:
假设我们有一个Student类,它包含id、name、age三个属性,我们希望按照id、name、age的顺序进行排序。我们提供以下比较器:
Comparator<Student> comparator = Comparator.comparing(Student::getId)
.thenComparing(Student::getName)
.thenComparing(Student::getAge);
Collections.sort(studentList, comparator);
但是,如果我们将两个Student实例视为相等,并且将它们与一个新的空实例进行比较,则会违反传递性规则。因此,我们可以将比较器中的null值处理交给每个属性的getter方法:
Comparator<Student> comparator = Comparator.comparing(Student::getId,
Comparator.nullsFirst(Integer::compareTo))
.thenComparing(Student::getName,
Comparator.nullsFirst(String::compareToIgnoreCase))
.thenComparing(Student::getAge,
Comparator.nullsFirst(Integer::compareTo));
Collections.sort(studentList, comparator);
这样,我们就可以避免“Comparison method violates its general contract”异常。
总之,当我们遇到“Comparison method violates its general contract”异常时,需要仔细检查我们的比较器,确保它遵循反射性、对称性、传递性三个基本规则,同时在比较null值时进行适当处理,以避免这种异常的出现。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java中排序报:Comparison method violates its general contract异常的解决 - Python技术站