TimSort是一种混合排序算法,由Tim Peters于2002年设计,并成为Python中list.sort()的默认实现,它结合了归并排序和插入排序的优点,以在真实世界中的各种数据上表现出较好的性能,在使用TimSort时,有时会遇到报错的情况,Comparison method violates its general contract!”,本文将详细解释TimSort报错的原因、解决方法以及相关FAQs。
TimSort报错的原因及解决方法
一、原因分析

1、比较方法违反了一般契约:TimSort要求比较方法必须满足以下三个特性:
自反性:x与y的比较结果和y与x的比较结果相反。
传递性:如果x > y且y > z,则x > z。
对称性:如果x = y,则x与任何z的比较结果和y与z的比较结果相同。
如果不满足这些特性,就会抛出“Comparison method violates its general contract!”异常,以下代码会导致该错误:
- public int compareTo(OrgChartBean o) {
- if (o == null || o.getCount() < getCount()) {
- return 1;
- }
- return 1;
- }
上述代码未处理o.getCount() == getCount()
的情况,导致不满足对称性。

2、数组长度大于等于32时合并操作触发的错误:当数组长度较大时,TimSort会将数组分成多个run进行排序,然后合并这些run,如果合并过程中出现不符合预期的情况,也可能导致报错。
二、解决方法
1、修正比较方法:确保比较方法满足TimSort的三个特性,修正后的代码如下:
- public int compareTo(OrgChartBean o) {
- if (o == null || o.getCount() < getCount()) {
- return 1;
- } else if (o.getCount() > getCount()) {
- return 1;
- } else {
- return 0;
- }
- }
2、使用旧版排序方法:如果不想修改比较方法,可以设置系统属性java.util.Arrays.useLegacyMergeSort
为true,使用旧的排序方法(非TimSort),但这种方法不推荐,因为无法享受TimSort带来的性能优势。
- System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
示例代码及分析
以下是一个完整的示例代码,演示如何生成一个包含32个元素的随机数列表,并使用TimSort进行排序,如果比较方法不正确,将抛出异常。
- import java.util.*;
- public class TimSortExample {
- public static void main(String[] args) {
- List<OrgChartBean> resultList = new ArrayList<OrgChartBean>(32);
- long[] a = new long[]{13, 14, 35, 11, 8, 33, 15, 29, 12, 0, 45, 20, 5, 37, 41, 9, 21, 7, 36, 6, 46, 22, 47, 32, 40, 5, 18, 27, 48, 16, 17, 23};
- for (int i = 0; i < 32; i++) {
- OrgChartBean bean = new OrgChartBean();
- bean.setCount(a[i]);
- resultList.add(bean);
- }
- String originalArr = resultList.toString();
- try {
- Collections.sort(resultList);
- } catch (Exception e) {
- System.out.println(resultList);
- System.out.println(originalArr);
- throw e;
- }
- }
- }
- class OrgChartBean implements Comparable<OrgChartBean>, Serializable {
- private static final long serialVersionUID = 1L;
- private long count;
- public OrgChartBean() {
- super();
- }
- public long getCount() {
- return count;
- }
- public void setCount(long count) {
- this.count = count;
- }
- @Override
- public int compareTo(OrgChartBean o) {
- if (o == null || o.getCount() < getCount()) {
- return 1;
- } else if (o.getCount() > getCount()) {
- return 1;
- } else {
- return 0;
- }
- }
- @Override
- public String toString() {
- return "" + count;
- }
- }
TimSort作为一种高效的排序算法,广泛应用于各种编程语言中,要正确使用TimSort,必须确保比较方法符合其要求的三个特性:自反性、传递性和对称性,如果遇到“Comparison method violates its general contract!”异常,通常是因为比较方法不符合这些特性,通过修正比较方法或使用旧版排序方法,可以解决这一问题,TimSort的设计初衷是为了在真实世界的数据中提供更好的性能,因此在实际应用中应尽量遵循其规则,以发挥其最大优势。