天天看點

Java中Collections.sort()方法的演變結果分析源碼分析關于Java8中Collections.sort方法的修改

先看一段代碼

List<Integer> list = new ArrayList<Integer>();
  list.add(1);
  list.add(2);
  list.add(3);

  Iterator<Integer> it = list.iterator();

  Collections.sort(list);

  while (it.hasNext()) {
   System.out.println(it.next());
  }
           

Java7 運作效果

1
2
3
           

Java8 運作效果

Java中Collections.sort()方法的演變結果分析源碼分析關于Java8中Collections.sort方法的修改

結果分析

在上面的代碼中,我們先得到list的iterator,然後對list進行排序,最後周遊iterator。

從Java8的錯誤資訊中可以看出it.next( )方法中檢查list是否已經被修改,由于在周遊之前進行了一次排序,是以checkForComodification方法抛出異常ConcurrentModificationException。

這個可以了解,因為排序,肯定會修改list

但是為啥Java7中沒問題呢?

源碼分析

首先看checkForComodification方法是如何判斷的,如下所示:

final void checkForComodification() {
  if (modCount != expectedModCount)
    throw new ConcurrentModificationException();
}
           

可以看出,有兩個内部成員變量用來判斷是否發生了修改: modCount 和 expectedModCount。

Iterator中記錄了expectedModCount

List中記錄了modCount

checkForComodification方法通過比較modCount 和 expectedModCount來判斷是否發生了修改。

在Java7中,Collections.sort( list )調用的是Collections自身的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]);
   }
}
           

可以看出,該排序算法隻是改變了List中元素的值(i.set((T)a[j]);),并沒有修改modCount字段。是以checkForComodification方法不會抛出異常。

而在Java8中,Collections.sort( list )調用的是ArrayList自身的sort方法,如下所示:

public static <T extends Comparable<? super T>> void sort(List<T> list) {

list.sort(null);

}

ArrayList的sort方法實作如下:

Java中Collections.sort()方法的演變結果分析源碼分析關于Java8中Collections.sort方法的修改

可以看出最後一行,modCount++修改了modCount字段

是以checkForComodification方法會抛出異常

關于Java8中Collections.sort方法的修改

之前,Collection.sort複制list中的元素以排序到數組中,對數組進行排序,然後使用數組中的元素更新清單,并将預設方法List.sort委托給Collection.sort。這不是一個最佳的設計

從8u20釋出起,Collection.sort将被委托給List.sort,這意味着,例如,現有的以ArrayList執行個體調用Collection.sort的代碼将使用由ArrayList實作的最佳排序