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 运行效果

结果分析

在上面的代码中,我们先得到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方法实现如下:

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

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

之前,Collection.sort复制list中的元素以排序到数组中,对数组进行排序,然后使用数组中的元素更新列表,并将默认方法List.sort委托给Collection.sort。这不是一个最佳的设计 从8u20发布起,Collection.sort将被委托给List.sort,这意味着,例如,现有的以ArrayList实例调用Collection.sort的代码将使用由ArrayList实现的最佳排序

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java帮帮-微信公众号-技术文章全总结

HashSet 源码分析【面试+工作】

在工作中,经常有这样的需求,需要判断某个ID是否在某个组的管理之下等,就需要查询该组下的ID放到一个集合中,且集合中元素不能有重复,之后判断该集合是否包含我们的...

12630
来自专栏文武兼修ing——机器学习与IC设计

二叉查找树二叉查找树

二叉查找树 二叉查找树是一种特殊的二叉树,该数据结构的核心性质是: 对于树中的每个节点X,它的左子树中所有关键字值小于X的关键字值,而它的右子树中所有关键字值...

304110
来自专栏数据结构与算法

2879 堆的判断

2879 堆的判断 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 黄金 Gold 题目描述 Description 堆是一种常用...

32580
来自专栏java系列博客

Java ConcurrentModificationException异常原因和解决方法

86820
来自专栏TechBox

数据结构与算法之线性表前言线性表

19750
来自专栏mathor

Map

15540
来自专栏恰童鞋骚年

数据结构基础温故-4.树与二叉树(下)

上面两篇我们了解了树的基本概念以及二叉树的遍历算法,还对二叉查找树进行了模拟实现。数学表达式求值是程序设计语言编译中的一个基本问题,表达式求值是栈应用的一个典型...

10820
来自专栏Android机动车

数据结构学习笔记——线性表(中)

线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的。这就意味着,这些数据元素可以存在内存未被占用的...

9430
来自专栏haifeiWu与他朋友们的专栏

聊聊HashSet源码

今天聊一下HashSet源码,HashSet内部基本使用HashMap来实现,本博客将通过一下几个方向讲解。

9730
来自专栏电光石火

HashSet/HashMap详解

HashMap和HashSet是Java Collection接口两个重要的成员,其中HashMap是Map接口常用的实现类,HashSet是Set接口常用...

240100

扫码关注云+社区

领取腾讯云代金券