java7排序

    在使用jdk1.7后发现,部分使用排序的列表变了。然后就可劲的找原因。最后发现:

 

首先进入Collection.sort方法

    public static <T extends Comparable<? super T>> void sort(List<T> list) {
        Object[] a = list.toArray();
        Arrays.sort(a);
        ListIterator<T> i = list.listIterator();
        for (int j=0; j<a.length; j++) {
            i.next();
            i.set((T)a[j]);
        }
    }

 本质就是对数组进行排序然后输出。

 

再进入Arrays.sort()方法

    public static void sort(Object[] a) {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a);
        else
            ComparableTimSort.sort(a);
    }

 看到这,其实也里看到点东西了,哈哈userRequested,再点进去

    static final class LegacyMergeSort {
        private static final boolean userRequested =
            java.security.AccessController.doPrivileged(
                new sun.security.action.GetBooleanAction(
                    "java.util.Arrays.useLegacyMergeSort")).booleanValue();
    }

 原来如此,在JVM中配置-Djava.util.Arrays.useLegacyMergeSort=true ,就可以使用传统的归并排序了。

到此为止,已经解决为什么JDK1.7的排序会与JDK1.6不致的问题的。下面我们来深入的看下这两个排序方式的迥异:

legacyMergeSort()核心实现

    private static void mergeSort(Object[] src,
                                  Object[] dest,
                                  int low,
                                  int high,
                                  int off) {
        int length = high - low;

        // Insertion sort on smallest arrays
        if (length < INSERTIONSORT_THRESHOLD) {
            for (int i=low; i<high; i++)
                for (int j=i; j>low &&
                         ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
                    swap(dest, j, j-1);
            return;
        }

        // Recursively sort halves of dest into src
        int destLow  = low;
        int destHigh = high;
        low  += off;
        high += off;
        int mid = (low + high) >>> 1;
        mergeSort(dest, src, low, mid, -off);
        mergeSort(dest, src, mid, high, -off);

        // If list is already sorted, just copy from src to dest.  This is an
        // optimization that results in faster sorts for nearly ordered lists.
        if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
            System.arraycopy(src, low, dest, destLow, length);
            return;
        }

        // Merge sorted halves (now in src) into dest
        for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
            if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0)
                dest[i] = src[p++];
            else
                dest[i] = src[q++];
        }
    }

 排序个数小于7,直接使用插入排序,时间复杂度为O(n2),适用于小数据排序。其它部分典型的归并排序实现法。不过人家写的确实高效率 int mid = (low + high) >>> 1; 给我们肯定直接就成了int mid=(low+high)/2;

 

ComparableTimSort.sort(a)核心实现

        rangeCheck(a.length, lo, hi);
        int nRemaining  = hi - lo;
        if (nRemaining < 2)
            return;  // Arrays of size 0 and 1 are always sorted

        // If array is small, do a "mini-TimSort" with no merges
        if (nRemaining < MIN_MERGE) {
            int initRunLen = countRunAndMakeAscending(a, lo, hi);
            binarySort(a, lo, hi, lo + initRunLen);
            return;
        }

        /**
         * March over the array once, left to right, finding natural runs,
         * extending short natural runs to minRun elements, and merging runs
         * to maintain stack invariant.
         */
        ComparableTimSort ts = new ComparableTimSort(a);
        int minRun = minRunLength(nRemaining);
        do {
            // Identify next run
            int runLen = countRunAndMakeAscending(a, lo, hi);

            // If run is short, extend to min(minRun, nRemaining)
            if (runLen < minRun) {
                int force = nRemaining <= minRun ? nRemaining : minRun;
                binarySort(a, lo, lo + force, lo + runLen);
                runLen = force;
            }

            // Push run onto pending-run stack, and maybe merge
            ts.pushRun(lo, runLen);
            ts.mergeCollapse();

            // Advance to find next run
            lo += runLen;
            nRemaining -= runLen;
        } while (nRemaining != 0);

        // Merge all remaining runs to complete sort
        assert lo == hi;
        ts.mergeForceCollapse();
        assert ts.stackSize == 1;
    

 ComparableTimSort来源于GOOGLE,详见下文

 

 

两个对象直接比如定义Comparator

public double compare(Object o1, Object o2) {
		ComparaContainer tr1 = (ComparaContainer) o1;
		ComparaContainer tr2 = (ComparaContainer) o2;

		if (tr1.getCompareValue() < tr2.getCompareValue()) {
			return (tr1.getCompareValue()-tr2.getCompareValue());
		} else if (tr1.getCompareValue() == tr2.getCompareValue()) {
			return tr1.getSecondValue() <= tr2.getSecondValue() ? 0 : 1;
		} else {
			return 1;
		}
}

 

由于1.7改得更为严谨不能直接使用-1,0,1来表示小于、等于、大于

得改用a-b

 

如下所示

	public int compare(Object o1, Object o2) {
		ComparaContainer tr1 = (ComparaContainer) o1;
		ComparaContainer tr2 = (ComparaContainer) o2;
		double m = tr1.getCompareValue()-tr2.getCompareValue();
		if (tr1.getCompareValue() < tr2.getCompareValue()) {
			return (int)m;
		} else if (tr1.getCompareValue() == tr2.getCompareValue()) {
			m = tr1.getSecondValue()- tr2.getSecondValue();
			return (int)m;
		} else {
			return (int)m;
		}
	}

 

或者最简单的是将原来return 0;的改成return -1; 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值