java集合类(一),java List , ArrayList 排序方法源码解析

java 8

ArrayList.sort() 方法

   @Override
    @SuppressWarnings("unchecked")
    public void sort(Comparator<? super E> c) {
        //1、用于并发的计数器
        final int expectedModCount = modCount;
        //2、用数组的方法,进行排序
        Arrays.sort((E[]) elementData, 0, size, c);
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }

画重点:
(1)源码中的 elementData 是 new ArrayList()时候创建的

/**DEFAULTCAPACITY_EMPTY_ELEMENTDATA 代码: private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; 是个Object 的数组 */
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

ArrayList 的add方法就是不断的相当于在上组上 添加元素

/**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    

(2) Arrays.sort 源码

public static <T> void sort(T[] a, int fromIndex, int toIndex,
                                Comparator<? super T> c) {
        if (c == null) {
            //1.排序规则为空的时候的默认排序
            sort(a, fromIndex, toIndex);
        } else {
            //2. rangeCheck 方法用作检查数组越界等异常
            rangeCheck(a.length, fromIndex, toIndex);
            if (LegacyMergeSort.userRequested)
                //3.字面理解 剩余归并排序
                legacyMergeSort(a, fromIndex, toIndex, c);
            else
                //4.排序
                TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0);
        }
    }
    

sort() 方法源码解释

public static void sort(Object[] a, int fromIndex, int toIndex) {
        rangeCheck(a.length, fromIndex, toIndex);
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a, fromIndex, toIndex);
        else
            ComparableTimSort.sort(a, fromIndex, toIndex, null, 0, 0);
    }

上面同样是sort 方法,是上面sort 的重写
rangeCheck() 方法, 校验数组规则,由此可见我们使用ArrayList 的时候ArrayIndexOutOfBoundsException 是咋出现的了,(toIndex > arrayLength) 当toIndex(arrayList 的 add 方法会增大) 长度大于 arrayLength (arrayList 对应的数组长度)的时候

/**
     * Checks that {@code fromIndex} and {@code toIndex} are in
     * the range and throws an exception if they aren't.
     */
    private static void rangeCheck(int arrayLength, int fromIndex, int toIndex) {
        if (fromIndex > toIndex) {
            throw new IllegalArgumentException(
                    "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
        }
        if (fromIndex < 0) {
            throw new ArrayIndexOutOfBoundsException(fromIndex);
        }
        if (toIndex > arrayLength) {
            throw new ArrayIndexOutOfBoundsException(toIndex);
        }
    }

TimSort.sort() 源码

    static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
                         T[] work, int workBase, int workLen) {
        assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;
        //1. 数组的剩余个数
        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 ,数组是小的(MIN_MERGE 是 32),不进行归并
        if (nRemaining < MIN_MERGE) {
           //countRunAndMakeAscending 返回 int,解释见 countRunAndMakeAscending 源码
            int initRunLen = countRunAndMakeAscending(a, lo, hi, c);
            //二分排序
            binarySort(a, lo, hi, lo + initRunLen, c);
            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.
         */
        TimSort<T> ts = new TimSort<>(a, c, work, workBase, workLen);
        int minRun = minRunLength(nRemaining);
        do {
            // Identify next run
            int runLen = countRunAndMakeAscending(a, lo, hi, c);

            // 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, c);
                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;
    }

countRunAndMakeAscending 方法的源码


  private static <T> int countRunAndMakeAscending(T[] a, int lo, int hi,
                                                  Comparator<? super T> c) {
      assert lo < hi;
      int runHi = lo + 1;  
      if (runHi == hi)
          return 1;

      // Find end of run, and reverse range if descending
      //小于0 则调整数组的顺序,compare 方法看见了arrayList.sort 方法进行排序的那个规则
      if (c.compare(a[runHi++], a[lo]) < 0) { // Descending
         // 
          while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)
              runHi++;
          reverseRange(a, lo, runHi);
      } else {                              // Ascending
          while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0)
              runHi++;
      }

      return runHi - lo;
  }

reverseRange 源码

  private static void reverseRange(Object[] a, int lo, int hi) {
        hi--;
        while (lo < hi) {
            Object t = a[lo];
            a[lo++] = a[hi];
            a[hi--] = t;
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值