Java 8 Collections.sort 新实现

先看一段代码

  List list = new ArrayList();
  list.add(1);
  list.add(2);
  list.add(3);
  list.add(4);
  list.add(5);

  Iterator it = list.iterator();

  Collections.sort(list);

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

Java7 运行效果

1
2
3
4
5

Java8 运行效果 (异常ConcurrentModificationException)

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)

结果分析

在上面的代码中,我们先得到listiterator,然后对list进行排序,最后遍历iterator
从Java8的错误信息中可以看出it.next( )方法中检查list是否已经被修改,由于在遍历之前进行了一次排序,所以checkForComodification方法抛出异常ConcurrentModificationException
这个可以理解,因为排序嘛,肯定会修改list...
但是为啥Java7中没有这个问题呢???

源码分析

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

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

可以看出,有两个内部成员变量用来判断是否发生了修改: modCountexpectedModCount

Iterator中记录了expectedModCount,List中记录了modCountcheckForComodification方法通过比较modCountexpectedModCount来判断是否发生了修改。

在Java7中,Collections.sort( list )调用的是Collections自身的sort方法,如下所示:

public static > void sort(List list) {
   Object[] a = list.toArray();
   Arrays.sort(a);
   ListIterator i = list.listIterator();
   for (int j=0; j

可以看出,该排序算法只是改变了List中元素的值(i.set((T)a[j]);),并没有修改modCount字段。所以checkForComodification方法不会抛出异常。

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

public static > void sort(List list) {
  list.sort(null);
}

ArrayList的sort方法实现如下:

public void sort(Comparator c) {
  final int expectedModCount = modCount;
  Arrays.sort((E[]) elementData, 0, size, c);
  if (modCount != expectedModCount) {
    throw new ConcurrentModificationException();
  }
  modCount++;
}

可以看出最后一行,modCount++;,修改了modCount字段。所以checkForComodification方法会抛出异常。

关于Java8中Collections.sort方法的修改,可以参见官方描述:

Previously Collection.sort copied the elements of the list to sort into an array, sorted that array, then updated list, in place, with those elements in the array, and the default method List.sort deferred to Collection.sort. This was a non-optimal arrangement.
From 8u20 release onwards Collection.sort defers to List.sort. This means, for example, existing code that calls Collection.sort with an instance of ArrayList will now use the optimal sort implemented by ArrayList.

引用:Collection.sort defers now defers to List.sort

你可能感兴趣的:(Java 8 Collections.sort 新实现)