Java 8 Collections.sort 新实现

先看一段代码

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

  Iterator<Integer> 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 <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方法实现如下:

public void sort(Comparator<? super E> 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.Java集合框架是什么?说出一些集合框架的优点? 每种编程语言中都有集合,最初的Java版本包含几种集合类:V...
    独念白阅读 4,233评论 0 2
  • Java 语言支持的类型分为两类:基本类型和引用类型。整型(byte 1, short 2, int 4, lon...
    xiaogmail阅读 5,160评论 0 10
  • 接着Java集合框架学习---深入探究ArrayList源码(二)继续学习ArrayList源码。 removeA...
    EakonZhao阅读 4,592评论 0 6
  • Java源码研究之容器(1) 如何看源码 很多时候我们看源码, 看完了以后经常也没啥收获, 有些地方看得懂, 有些...
    骆驼骑士阅读 4,565评论 0 22
  • 身在海外,想看中文书,可以看电子书,网上下载,或者在二手书群里淘一下。 孩子们的书呢,德文绘本在小村图书馆里种类齐...
    半山桃源阅读 1,560评论 0 2