Comparison method violates its general contract!

参考文献:

  1. 图解JDK7的Comparison method violates its general contract异常 http://blog.2baxb.me/archives/993

 

在用Collections.sort排序时出现了这个错误:Comparison method violates its general contract!

找了好久的问题,也没有找到最终解决方案,从网上查询,说是JDK7的问题

JDK7中的Collections.Sort方法实现中,如果两个值是相等的,那么compare方法需要返回0,否则可能会在排序时抛错,而JDK6是没有这个限制的。看TimSort.class中是在mergeHi方法这个位置报错的,这个方案里参数已经提示了:len2长度必须大于0

TimSort.class的源码:

/**
     * Like mergeLo, except that this method should be called only if
     * len1 >= len2; mergeLo should be called if len1 <= len2.  (Either method
     * may be called if len1 == len2.)
     *
     * @param base1 index of first element in first run to be merged
     * @param len1  length of first run to be merged (must be > 0)
     * @param base2 index of first element in second run to be merged
     *        (must be aBase + aLen)
     * @param len2  length of second run to be merged (must be > 0)
     */
    private void mergeHi(int base1, int len1, int base2, int len2) {
        assert len1 > 0 && len2 > 0 && base1 + len1 == base2;

        // Copy second run into temp array
        T[] a = this.a; // For performance
        T[] tmp = ensureCapacity(len2);
        System.arraycopy(a, base2, tmp, 0, len2);

        int cursor1 = base1 + len1 - 1;  // Indexes into a
        int cursor2 = len2 - 1;          // Indexes into tmp array
        int dest = base2 + len2 - 1;     // Indexes into a

        // Move last element of first run and deal with degenerate cases
        a[dest--] = a[cursor1--];
        if (--len1 == 0) {
            System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
            return;
        }
        if (len2 == 1) {
            dest -= len1;
            cursor1 -= len1;
            System.arraycopy(a, cursor1 + 1, a, dest + 1, len1);
            a[dest] = tmp[cursor2];
            return;
        }

        Comparator<? super T> c = this.c;  // Use local variable for performance
        int minGallop = this.minGallop;    //  "    "       "     "      "
    outer:
        while (true) {
            int count1 = 0; // Number of times in a row that first run won
            int count2 = 0; // Number of times in a row that second run won

            /*
             * Do the straightforward thing until (if ever) one run
             * appears to win consistently.
             */
            do {
                assert len1 > 0 && len2 > 1;
                if (c.compare(tmp[cursor2], a[cursor1]) < 0) {
                    a[dest--] = a[cursor1--];
                    count1++;
                    count2 = 0;
                    if (--len1 == 0)
                        break outer;
                } else {
                    a[dest--] = tmp[cursor2--];
                    count2++;
                    count1 = 0;
                    if (--len2 == 1)
                        break outer;
                }
            } while ((count1 | count2) < minGallop);

            /*
             * One run is winning so consistently that galloping may be a
             * huge win. So try that, and continue galloping until (if ever)
             * neither run appears to be winning consistently anymore.
             */
            do {
                assert len1 > 0 && len2 > 1;
                count1 = len1 - gallopRight(tmp[cursor2], a, base1, len1, len1 - 1, c);
                if (count1 != 0) {
                    dest -= count1;
                    cursor1 -= count1;
                    len1 -= count1;
                    System.arraycopy(a, cursor1 + 1, a, dest + 1, count1);
                    if (len1 == 0)
                        break outer;
                }
                a[dest--] = tmp[cursor2--];
                if (--len2 == 1)
                    break outer;

                count2 = len2 - gallopLeft(a[cursor1], tmp, 0, len2, len2 - 1, c);
                if (count2 != 0) {
                    dest -= count2;
                    cursor2 -= count2;
                    len2 -= count2;
                    System.arraycopy(tmp, cursor2 + 1, a, dest + 1, count2);
                    if (len2 <= 1)  // len2 == 1 || len2 == 0
                        break outer;
                }
                a[dest--] = a[cursor1--];
                if (--len1 == 0)
                    break outer;
                minGallop--;
            } while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP);
            if (minGallop < 0)
                minGallop = 0;
            minGallop += 2;  // Penalize for leaving gallop mode
        }  // End of "outer" loop
        this.minGallop = minGallop < 1 ? 1 : minGallop;  // Write back to field

        if (len2 == 1) {
            assert len1 > 0;
            dest -= len1;
            cursor1 -= len1;
            System.arraycopy(a, cursor1 + 1, a, dest + 1, len1);
            a[dest] = tmp[cursor2];  // Move first elt of run2 to front of merge
        } else if (len2 == 0) {
            throw new IllegalArgumentException(
                "Comparison method violates its general contract!");//!!!这儿抛出的异常
        } else {
            assert len1 == 0;
            assert len2 > 0;
            System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
        }
    }

报错代码源码:

List<Comparator<SalesSchemeOrderItemTreeVO>> comparators = new ArrayList<Comparator<SalesSchemeOrderItemTreeVO>>();
comparators.add(new Comparator<SalesSchemeOrderItemTreeVO>() {
		@Override
		public int compare(SalesSchemeOrderItemTreeVO o1, SalesSchemeOrderItemTreeVO o2) {
			if(StringUtils.isNotBlank(o1.getSpaceCode()) && StringUtils.isNotBlank(o2.getSpaceCode())) {
				return o1.getSpaceCode().compareTo(o2.getSpaceCode());  
			} else if(StringUtils.isNotBlank(o1.getSpaceName()) && StringUtils.isNotBlank(o2.getSpaceName())){
				return o1.getSpaceName().compareTo(o2.getSpaceName());
			} else {
				return -1;
			}
		} 
	});
comparators.add(new Comparator<SalesSchemeOrderItemTreeVO>() {
	@Override
	public int compare(SalesSchemeOrderItemTreeVO o1, SalesSchemeOrderItemTreeVO o2) {
		if(null == o1 || null == o2) {
			return -1;
		} else if(StringUtils.isNotBlank(o1.getProdCatId()) && StringUtils.isNotBlank(o2.getProdCatId())) {
			return o1.getProdCatId().compareTo(o2.getProdCatId());  
		} else {
			return -1;
		}
	} 
});
comparators.add(new Comparator<SalesSchemeOrderItemTreeVO>() {
		@Override
		public int compare(SalesSchemeOrderItemTreeVO o1, SalesSchemeOrderItemTreeVO o2) {
			if(StringUtils.isNotBlank(o1.getBrandGoodsIdName()) && StringUtils.isNotBlank(o2.getBrandGoodsIdName())) {
				return o1.getBrandGoodsIdName().compareTo(o2.getBrandGoodsIdName());
			} else {
				return -1;
			}
		} 
});
Collections.sort(itemTreeVO, new ComparatorChain(comparators));

 

这个问题目前我还是没有理解透,待理解透后再把具体的解决办法写出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值