ArrayList源碼解析 經典排序算法--歸併排序

ArrayList源碼解析

ArrayList簡介:

ArrayList 是list接口的一個經常使用實現類。它的對象能夠認爲是一維數組的「類版本」。咱們很快就能夠看到,ArrayList 對象能夠看作是一維數組的改良版本。相似於數組,ArrayList 對象支持元素的隨機訪問;也就是說,只要給出元素的索引,任何元素的訪問時間都是常數。可是同數組不一樣的是,ArrayList 對象的大小在程序執行的過程當中能夠自動進行調整,而且ArrayList對象具備在任何索引位置插入和刪除對象的方法,而數組若是想要插入和刪除對象,則必需要編寫代碼增長和減小儲存空間。

ArrayList方法簡介:

首先咱們先來看一下ArrayList的全部公共方法。html

注:下面方法除構造函數方法外,其餘方法皆按照字母順序排序。java

 1 一、public Arraylist()
 2 二、public ArrayList(int initalCapacity)
 3 三、public ArrayList(Collection<? extends E> c)
 4 四、public boolean add(E e)
 5 五、public void add(int index, E element)
 6 六、 public boolean addAll(int index, Collection<? extends E> c)
 7 七、public boolean addAll(Collection<? extends E> c)
 8 八、 public void clear()
 9 九、 public Object clone()
10 十、 public boolean contains(Object o)
11 十一、public boolean containsAll(Collection<?> c)
12 十二、public void ensureCapacity(int minCapacity)
13 1三、public boolean equals(Object o)
14 1四、 public void forEach(Consumer<? super E> action)
15 1五、public E get(int index)
16 1六、public int hashCode()
17 1七、 public int indexOf(Object o)
18 1八、public boolean isEmpty()
19 1九、public Iterator<E> iterator()
20 20、public int lastIndexOf(Object o)
21 2一、public ListIterator<E> listIterator()
22 2二、public ListIterator<E> listIterator(int index)
23 2三、public E remove(int index)
24 2四、public boolean remove(Object o)
25 2五、public boolean removeAll(Collection<?> c)
26 2六、public boolean removeIf(Predicate<? super E> filter)
27 2七、 public void replaceAll(UnaryOperator<E> operator)
28 2八、public boolean retainAll(Collection<?> c)
29 2九、public E set(int index, E element)
30 30、public int size()
31 3一、public void sort(Comparator<? super E> c)
32 3二、public Spliterator<E> spliterator()
33 3三、public List<E> subList(int fromIndex, int toIndex)
34 3四、public Object[] toArray()
35 3五、public <T> T[] toArray(T[] a)
36 3六、public String toString()
37 3七、public void trimToSize()
View Code

ArrayList方法解析:

ArrayList類結構關係:

在具體分析Arrayl類的方法以前,咱們先看一下ArrayList類的繼承關係。
 
從圖中能夠看出,ArrayList繼承AbstractList類,而且實現了List、RandomAccess、Serializable接口。
其中RandomAccess接口爲一個空接口,起到一個標識的做用,若是集合類是RandomAccess的實現,則儘可能用for(int i = 0; i < size; i++) 來遍歷而不要用Iterator迭代器來遍歷,在效率上要差一些。反過來,若是List是Sequence List,則最好用迭代器來進行迭代。 其具體細節在咱們在這裏就不進行討論了,感興趣的同窗能夠本身去查一查。
Serializable是啓用序列化功能的接口,這裏也不進行討論了。
AbstractList繼承了AbstractCollection.二者都是抽象類,AbstractCollection提供了Collection接口的一些方法的默認實現,AbstractCollection提供了List接口
的默認實現(個別方法爲抽象方法)。

ArrayList類的屬性:

 1 //默認容量的大小
 2 private static final int DEFAULT_CAPACITY = 10;
 3 
 4 //空數組常量
 5 private static final Object[] EMPTY_ELEMENTDATA = {};
 6 
 7 //默認的空數組常量
 8 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
 9 
10 //存放元素的數組,從這能夠發現ArrayList的底層實現就是一個Object數組
11 transient Object[] elementData;
12 
13 //數組中包含的元素個數
14 private int size;
15 
16 //數組的最大上限
17 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
View Code

ArrayList的屬性很是少,一共就只有這五個。其中:DEFAULT_CAPACITY 表明默認容量的大小,在後面咱們能夠看到,在像ArrayList對象第一次添
加元素的時候,會將ArrayList的容量設置爲默認的容量。EMPTY_ELEMENTDATE和DEFAULTCAPACITY_EMPTY_ELEMENTDATA區別不大。這個在後面
講構造器的時候會詳細講到。其中最重要的莫過於elementData了,ArrayList全部的方法都是創建在elementData之上。

ArrayList構造函數:

ArrayList一共有三個構造函數,分別爲:算法

 1 public ArrayList(int initialCapacity) {
 2         if (initialCapacity > 0) {
 3             this.elementData = new Object[initialCapacity];
 4         } else if (initialCapacity == 0) {
 5             this.elementData = EMPTY_ELEMENTDATA;
 6         } else {
 7             throw new IllegalArgumentException("Illegal Capacity: "+
 8                                                initialCapacity);
 9         }
10     }
11     public ArrayList() {
12         this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
13     }
14     public ArrayList(Collection<? extends E> c) {
15         elementData = c.toArray();
16         if ((size = elementData.length) != 0) {
17             // c.toArray might (incorrectly) not return Object[] (see 6260652)
18             if (elementData.getClass() != Object[].class)
19                 elementData = Arrays.copyOf(elementData, size, Object[].class);
20         } else {
21             // replace with empty array.
22             this.elementData = EMPTY_ELEMENTDATA;
23         }
24     }
View Code
從構造函數咱們能夠看出,elementDate默認是一個大小爲0的的數組,即DEFAULTCAPACITY_EMPTY_ELEMENTDATA,而
當指定數組長度時,elementData的初始大小就變成了咱們所指定的初始大小了。若是咱們指定數組的默認長度爲0時,
elementDate即爲EMPTY_ELEMENTDATA,在這裏咱們還看不出二者的區別,在後面講到add方法時,就能夠看到二者的不一樣了。
ArrayList一樣能夠傳入一個Collection,當Collection不爲空時,複製該Collection。不然elementDate仍然爲EMPTY_ELEMENTDATA。

ArrayList的公共方法:

ArrayList的添加方法:

ArrayList添加單個元素有兩個方法,分別爲:
 1     public boolean add(E e) {
 2         ensureCapacityInternal(size + 1);  // Increments modCount!!
 3         elementData[size++] = e;
 4         return true;
 5     }
 6     public void add(int index, E element) {
 7         rangeCheckForAdd(index);
 8 
 9         ensureCapacityInternal(size + 1);  // Increments modCount!!
10         System.arraycopy(elementData, index, elementData, index + 1,
11                          size - index);
12         elementData[index] = element;
13         size++;
14     }
View Code

add(E e)方法是用來添加一個單個的元素,其調用了私有方法enesureCapacityInternal(size+1).數組

 1   private void ensureCapacityInternal(int minCapacity) {
 2         if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
 3             minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
 4         }
 5 
 6         ensureExplicitCapacity(minCapacity);
 7     }
 8     private void ensureExplicitCapacity(int minCapacity) {
 9         modCount++;//
10         // overflow-conscious code
11         if (minCapacity - elementData.length > 0)
12             grow(minCapacity);
13     }
14  private void grow(int minCapacity) {
15         // overflow-conscious code
16         int oldCapacity = elementData.length;
17         int newCapacity = oldCapacity + (oldCapacity >> 1);
18         if (newCapacity - minCapacity < 0)
19             newCapacity = minCapacity;
20         if (newCapacity - MAX_ARRAY_SIZE > 0)
21             newCapacity = hugeCapacity(minCapacity);
22         // minCapacity is usually close to size, so this is a win:
23         elementData = Arrays.copyOf(elementData, newCapacity);
24     }
咱們能夠看到,在這個方法中,增長了一個判斷,elementData ==DEFAULTCAPACITY_EMPTY_ELEMENTDATA,那麼minCapacity=DEFAULT_CAPACITY,也就是等於10.這就區分出了前面所說的DEFAULTCAPACITY_EMPTY_ELEMENTDATA和EMPTY_ELEMENTDATA的區別。當elemetnDate=DEFAULT_CAPACITY時,第一次添加元素時,容量變爲1,而當elementData =DEFAULTCAPACITY_EMPTY_ELEMENTDATA時,第一次添加元素時,容量變爲10.
同時,咱們也能夠看出ArrayList在面對容量不足時,每次擴容都是在原容量的基礎上,增長0.5倍。
而add(int index,E e)就比較好理解了,先檢查index,而後判斷是否須要擴容,須要就擴容,而後將原來的elemetnDate從index起始到最後複製到index+1的位置上,而後在原index位置添加元素。

 ArrayList添加多個元素的方法同樣有兩個,分別爲:app

 1     public boolean addAll(Collection<? extends E> c) {
 2         Object[] a = c.toArray();
 3         int numNew = a.length;
 4         ensureCapacityInternal(size + numNew);  // Increments modCount
 5         System.arraycopy(a, 0, elementData, size, numNew);
 6         size += numNew;
 7         return numNew != 0;
 8     }
 9 
10  public boolean addAll(int index, Collection<? extends E> c) {
11         rangeCheckForAdd(index);
12 
13         Object[] a = c.toArray();
14         int numNew = a.length;
15         ensureCapacityInternal(size + numNew);  // Increments modCount
16 
17         int numMoved = size - index;
18         if (numMoved > 0)
19             System.arraycopy(elementData, index, elementData, index + numNew,
20                              numMoved);
21 
22         System.arraycopy(a, 0, elementData, index, numNew);
23         size += numNew;
24         return numNew != 0;
25     }

插入多個元素,與插入單個元素的邏輯是同樣的,在這裏就再也不重複了。dom

ArrayList刪除元素方法:

ArrayList刪除元素的方法一共有五個,分別是ide

 1   public E remove(int index) {
 2         rangeCheck(index);
 3 
 4         modCount++;
 5         E oldValue = elementData(index);
 6 
 7         int numMoved = size - index - 1;
 8         if (numMoved > 0)
 9             System.arraycopy(elementData, index+1, elementData, index,
10                              numMoved);
11         elementData[--size] = null; // clear to let GC do its work
12 
13         return oldValue;
14     }

remove(int index)的處理邏輯:先檢查index是否大於elementDate的size,若是大於的話,則拋出異常;而後獲取elementDate[index],留在方法結束後返回;而後複製素組,從index+1開始,複製size-index-1個元素,複製到elementDate,從index開始;最後設置elementDate[--size]=null;函數

 

 1     public boolean remove(Object o) {
 2         if (o == null) {
 3             for (int index = 0; index < size; index++)
 4                 if (elementData[index] == null) {
 5                     fastRemove(index);
 6                     return true;
 7                 }
 8         } else {
 9             for (int index = 0; index < size; index++)
10                 if (o.equals(elementData[index])) {
11                     fastRemove(index);
12                     return true;
13                 }
14         }
15         return false;
16     }

remove(Object o)的邏輯:先判斷Object 是否爲null,若是爲null,則遍歷ArrayList,刪除全部的null值,若是有值被刪除,則返回true;若是Object不爲null,一樣遍歷ArrayList,刪除ArrayList中相同的元素,若是有元素被刪除,則返回true.post

而fastRemove(int index)的邏輯與remove(int index),徹底一致,只是少了對index的驗證。學習

1  public boolean removeAll(Collection<?> c) {
2         Objects.requireNonNull(c);
3         return batchRemove(c, false);
4     }
 1  private boolean batchRemove(Collection<?> c, boolean complement) {
 2         final Object[] elementData = this.elementData;
 3         int r = 0, w = 0;
 4         boolean modified = false;
 5         try {
 6             for (; r < size; r++)
 7                 if (c.contains(elementData[r]) == complement)
 8                     elementData[w++] = elementData[r];
 9         } finally {
10             // Preserve behavioral compatibility with AbstractCollection,
11             // even if c.contains() throws.
12             if (r != size) {
13                 System.arraycopy(elementData, r,
14                                  elementData, w,
15                                  size - r);
16                 w += size - r;
17             }
18             if (w != size) {
19                 // clear to let GC do its work
20                 for (int i = w; i < size; i++)
21                     elementData[i] = null;
22                 modCount += size - w;
23                 size = w;
24                 modified = true;
25             }
26         }
27         return modified;
28     }

從上面的代碼咱們能夠看出,remove(Collection<?> c)的邏輯:先判斷c是否爲null,若是爲null,則拋出異常。而後遍歷elementDate,若是c包含數組elementDate中的元素

,則將該元素添加一次替換原elementDate數組中,最後,將數組的其他位置設爲null,若是新數組比原來數組中的元素少,則已經刪除了元素,返回true.

 

除此以外,還有一個清空ArrayList的方法
1     public void clear() {
2         modCount++;
3 
4         // clear to let GC do its work
5         for (int i = 0; i < size; i++)
6             elementData[i] = null;
7 
8         size = 0;
9     }

clear()方法的邏輯:遍歷,刪除全部元素。

 

除此以外,還有一個retainAll(collenction<T> c)方法,該方法願意是取得兩個集合得交集,在這裏也能夠理解爲刪除集合中不與collection c 重複得元素。

 1 return batchRemove(c, true); 

能夠看到,它得處理邏輯和removeAll是一樣得邏輯,這裏就再也不重複了。

ArrayList修改元素的方法

在JDK1.8以前,修改元素只有一個方法,就是set(int index,Object c).

1  public E set(int index, E element) {
2         rangeCheck(index);
3 
4         E oldValue = elementData(index);
5         elementData[index] = element;
6         return oldValue;
7     }

邏輯很簡單,就是先檢查index,而後新元素替換舊元素,並返回舊元素。

在JDK1.8中,添加了一個新方法,批量修改replaceAll(UnaryOperator<E> operator):

 1 public void replaceAll(UnaryOperator<E> operator) {
 2         Objects.requireNonNull(operator);
 3         final int expectedModCount = modCount;
 4         final int size = this.size;
 5         for (int i=0; modCount == expectedModCount && i < size; i++) {
 6             elementData[i] = operator.apply((E) elementData[i]);
 7         }
 8         if (modCount != expectedModCount) {
 9             throw new ConcurrentModificationException();
10         }
11         modCount++;
12     }

 UnaryOperator<T> extends Function<T, T>,而Function<T,R>方法中有一個抽象方法,R apply<T,t>,方法的原意應該是將一個T轉換成R.而這裏使用,UnaryOperator,則只能將T轉換成T。咱們在使用ReplaceAll方法是,必須重寫apply方法,做爲轉換規則。例如:

 1 public class ArrayListTest {
 2     public static void main(String[] args) {
 3         List<String> list = new ArrayList<String>();
 4         list.add("科比");
 5         list.add("詹姆斯");
 6         list.add("庫裏");
 7         list.replaceAll(new UnaryOperator<String>() {
 8             @Override
 9             public String apply(String t) {
10                 // TODO Auto-generated method stub
11                 return t+"牛逼";
12             }
13         });
14         System.out.println(list);
15     }
16 }
輸出的結果爲:
[科比牛逼, 詹姆斯牛逼, 庫裏牛逼]

ArrayList查找元素得方法:

   

1    public E get(int index) {
2         rangeCheck(index);
3 
4         return elementData(index);
5     }

get(int index)方法,經過元素的下標來獲取元素。其原理就是獲取數組的當前下表的元素。

 1     public int indexOf(Object o) {
 2         if (o == null) {
 3             for (int i = 0; i < size; i++)
 4                 if (elementData[i]==null)
 5                     return i;
 6         } else {
 7             for (int i = 0; i < size; i++)
 8                 if (o.equals(elementData[i]))
 9                     return i;
10         }
11         return -1;
12     }

 indextOf(Object o),查找ArrayList是否含有某元素,且返回該元素在集合中的第一個位置的下標。經過遍歷元素,獲取該集合所含有的第一個該元素的下標。若是不含有該元素,則返回-1.

 1     public int lastIndexOf(Object o) {
 2         if (o == null) {
 3             for (int i = size-1; i >= 0; i--)
 4                 if (elementData[i]==null)
 5                     return i;
 6         } else {
 7             for (int i = size-1; i >= 0; i--)
 8                 if (o.equals(elementData[i]))
 9                     return i;
10         }
11         return -1;
12     }

lastIndexOf(Object o),與indexOf方法想法,該方法查找該元素在集合中最後一個位置,並返回下標。其邏輯與indexOf基本一致,只不過是在遍歷的時候選擇從後往前遍歷。

 1 public boolean isEmpty() { 2 return size == 0; 3 } 

isEmpth()方法用來查看集合是否爲空集合。若是size=0,則爲空集合,返回true。不然返回false。

  public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

 contains(Object o)查看集合中是否含有某元素。其調用indexOf(Object o),若是含有返回ture,不然返回false.

   public int size() {
        return size;
    }

 size()方法用來查看集合中含有多少個元素,返回元素個數。

ArrayList的一些其餘經常使用方法:

 1    public Object clone() {
 2         try {
 3             ArrayList<?> v = (ArrayList<?>) super.clone();
 4             v.elementData = Arrays.copyOf(elementData, size);
 5             v.modCount = 0;
 6             return v;
 7         } catch (CloneNotSupportedException e) {
 8             // this shouldn't happen, since we are Cloneable
 9             throw new InternalError(e);
10         }
11     }

clone()方法,用來複制集合並返回一個新的集合。而查看copyOf源碼,發現最底層是使用native方法進行的複製。我沒法肯定其究竟是深複製仍是淺複製。

  private static native Object newArray(Class<?> componentType, int length) throws NegativeArraySizeException; 

因此我寫了一個簡單的測試代碼,代碼以下:

 1 public class ArrayListTest{
 2     public static void main(String[] args) {
 3         ArrayList<User> list = new ArrayList<User>();
 4         list.add(new User("科比"));
 5         list.add(new User("詹姆斯"));
 6         list.add(new User("庫裏"));
 7         ArrayList list1= (ArrayList) list.clone();
 8         User user = list.get(1);
 9         user.name = "麥迪";
10         System.out.println(list1);
11     }
12 }
13 
14 class User{
15      String name;
16     public User(String name){
17         this.name = name;
18     }
19     @Override
20     public String toString() {
21         return name;
22     }
23 }

打印結果爲:

[科比, 麥迪, 庫裏]

  說明ArrayList的複製爲潛複製,由於其數組中的元素,並無進行值複製,而是直接複製了元素的引用。

 

在Java8中,ArrayList添加了一種新的遍歷方法。foreach+lambda表達式遍歷。代碼以下:

1 public class ArrayListTest{
2     public static void main(String[] args) {
3         ArrayList<String> list = new ArrayList<String>();
4         list.add("科比");
5         list.add("詹姆斯");
6         list.add("庫裏");
7         list.forEach((s)->System.out.println(s));
8     }
9 }

由於不懂lambda表達式的實現原理,foreach的源碼實在看不懂。等之後研究了lambda表達式的實現原理,在回來研究下foreach方法。

 在Java8中,ArrayList一樣新添加了一種排序方法。sort(Comparator<? super E> c).源碼以下:

 1  @Override
 2     @SuppressWarnings("unchecked")
 3     public void sort(Comparator<? super E> c) {
 4         final int expectedModCount = modCount;
 5         Arrays.sort((E[]) elementData, 0, size, c);
 6         if (modCount != expectedModCount) {
 7             throw new ConcurrentModificationException();
 8         }
 9         modCount++;
10     }

發現,ArrayList的排序,其實就是調用了數組的排序。咱們繼續往下看,數組是如何排序的:

 1     public static <T> void sort(T[] a, int fromIndex, int toIndex,
 2                                 Comparator<? super T> c) {
 3         if (c == null) {
 4             sort(a, fromIndex, toIndex);
 5         } else {
 6             rangeCheck(a.length, fromIndex, toIndex);
 7             if (LegacyMergeSort.userRequested)
 8                 legacyMergeSort(a, fromIndex, toIndex, c);
 9             else
10                 TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0);
11         }
12     }
1     public static void sort(Object[] a, int fromIndex, int toIndex) {
2         rangeCheck(a.length, fromIndex, toIndex);
3         if (LegacyMergeSort.userRequested)
4             legacyMergeSort(a, fromIndex, toIndex);
5         else
6             ComparableTimSort.sort(a, fromIndex, toIndex, null, 0, 0);
7     }
1  private static void legacyMergeSort(Object[] a,
2                                         int fromIndex, int toIndex) {
3         Object[] aux = copyOfRange(a, fromIndex, toIndex);
4         mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
5     }
 1 @SuppressWarnings({"unchecked", "rawtypes"})
 2     private static void mergeSort(Object[] src,
 3                                   Object[] dest,
 4                                   int low,
 5                                   int high,
 6                                   int off) {
 7         int length = high - low;
 8 
 9         // Insertion sort on smallest arrays
10         if (length < INSERTIONSORT_THRESHOLD) {
11             for (int i=low; i<high; i++)
12                 for (int j=i; j>low &&
13                          ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
14                     swap(dest, j, j-1);
15             return;
16         }
17 
18         // Recursively sort halves of dest into src
19         int destLow  = low;
20         int destHigh = high;
21         low  += off;
22         high += off;
23         int mid = (low + high) >>> 1;
24         mergeSort(dest, src, low, mid, -off);
25         mergeSort(dest, src, mid, high, -off);
26 
27         // If list is already sorted, just copy from src to dest.  This is an
28         // optimization that results in faster sorts for nearly ordered lists.
29         if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
30             System.arraycopy(src, low, dest, destLow, length);
31             return;
32         }
33 
34         // Merge sorted halves (now in src) into dest
35         for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
36             if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0)
37                 dest[i] = src[p++];
38             else
39                 dest[i] = src[q++];
40         }
41     }
1    /** To be removed in a future release. */
2     private static <T> void legacyMergeSort(T[] a, int fromIndex, int toIndex,
3                                             Comparator<? super T> c) {
4         T[] aux = copyOfRange(a, fromIndex, toIndex);
5         if (c==null)
6             mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
7         else
8             mergeSort(aux, a, fromIndex, toIndex, -fromIndex, c);
9     }
 1    @SuppressWarnings({"rawtypes", "unchecked"})
 2     private static void mergeSort(Object[] src,
 3                                   Object[] dest,
 4                                   int low, int high, int off,
 5                                   Comparator c) {
 6         int length = high - low;
 7 
 8         // Insertion sort on smallest arrays
 9         if (length < INSERTIONSORT_THRESHOLD) {
10             for (int i=low; i<high; i++)
11                 for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
12                     swap(dest, j, j-1);
13             return;
14         }
15 
16         // Recursively sort halves of dest into src
17         int destLow  = low;
18         int destHigh = high;
19         low  += off;
20         high += off;
21         int mid = (low + high) >>> 1;
22         mergeSort(dest, src, low, mid, -off, c);
23         mergeSort(dest, src, mid, high, -off, c);
24 
25         // If list is already sorted, just copy from src to dest.  This is an
26         // optimization that results in faster sorts for nearly ordered lists.
27         if (c.compare(src[mid-1], src[mid]) <= 0) {
28            System.arraycopy(src, low, dest, destLow, length);
29            return;
30         }
31 
32         // Merge sorted halves (now in src) into dest
33         for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
34             if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0)
35                 dest[i] = src[p++];
36             else
37                 dest[i] = src[q++];
38         }
39     }

能夠看出,當比較器爲空時,調用了mergeSort(Object[] src,Object[] dest,int low, int high, int off方法,不爲空時,調用了mergeSort(Object[] src,Object[] dest,int low, int high, int off,Comparator c方法,兩個方法基本如出一轍,惟一的區別就是在有默認比較器的時候,兩個元素的比較實用默認比較器的比較方法來比較。

仔細看兩個方法,能夠看出,ArrayList.sort方法 時間上是使用了一種優化事後的遞歸排序,在數組長度小於7的時候使用直接插入排序。數組長度大於7的時候,使用歸併排序,直至子數組的長度小於7.

歸併排序詳見個人另外一篇隨筆經典排序算法--歸併排序

 

寫在最後:
  此篇隨筆僅用來記錄個人學習內容,若有錯誤,歡迎指正。謝謝!!!
相關文章
相關標籤/搜索