专栏首页JavaEdgeJava中Collections.sort()方法的演变结果分析源码分析关于Java8中Collections.sort方法的修改

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 条评论
登录 后参与评论

相关文章

  • 适配器模式1 动机2 模式定义3 模式结构4 时序图5 代码分析8 优点9 缺点10 适用环境11 模式应用12 模式扩展13 总结

    JavaEdge
  • CSS 全解析实战(八)-Bootstrap1 Bootstrap介绍2 Bootstrap基本用法3 Bootstrap JS组件

    JavaEdge
  • SpringBoot+Security 发送短信验证码在core模块下properties包中创建SmsCodeProperties在ValidateCodeProperties中new一个SmsCo

    JavaEdge
  • AndroidStuio快速发布开源项目到Jcenter/Bintray

    1:AndroidStuio快速发布开源项目到Jcenter/Bintray 如何将自己开发的库,分享出去,让更多的人开发使用。就像你自己使用别人的库一样。比如...

    用户1263308
  • 承载WCF 数据服务

    WCF 数据服务默认使用IIS 作为 Data Service 宿主,很显然这是个极好的选择,我们可以利用 IIS 强大的基础功能。除此以外,我们页可以像 WC...

    张善友
  • 调研:软件公司收购额节节攀升 其动因是什么?

    T客汇官网:tikehui.com 编译:张苏月 ? 2016年被人们视为资本寒冬的一年,然而软件公司的收购却呈现出价高的趋势,究其原因则是企业模式变革的需...

    人称T客
  • 10-3 信号

    见贤思齊
  • Linux进程间通信(三) - 信号

    什么是信号 软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。在软件层次上是对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一...

    三丰SanFeng
  • AngularJS中使用表单输入的应用设计

    在Angular中使用表单元素非常方便。正如我们在前面几个例子中看到的,你可以使用ng-model属性把元素绑定到你的模型属性上。这一机制对于所有标准的表单元素...

    企鹅号小编
  • windows系统上openssh client的离线安装

    老是报错: PS C:\WINDOWS\system32>windowsCapabiity -Online ame -like 'OpenSSHGet-Wi...

    Jerry Wang

扫码关注云+社区

领取腾讯云代金券