首页>>后端>>java->List.sublist操作报错

List.sublist操作报错

时间:2023-12-06 本站 点击:0

背景

我们在日常开发中经常会使用List对数据进行排序、查找、截取等操作。接下来我们看下因为List截取导致的踩坑现场。

【问题描述】

在正常的业务需求迭代过程中,我们需要对List里的数据进行截取,并生成新的subList,然后对原有的list进行add/remove操作,结果导致我们的subList循环、add/remove等操作报错。

【故障现象】

抛出异常: Exception in thread "main" java.util.ConcurrentModificationException

问题复现:

首先我们先用一段代码复现问题根源,如下所示:

new一个list

增加三个测试数据

new一个sublist,并且list.sublist(0,1)存储新的数据

原list新增一个测试数据no4

循环sublist报错

public static void main(String[] args) {  List<String> list = new ArrayList<>();  list.add("no1");  list.add("no2");  list.add("no3");  List<String>subList=list.subList(0,1);  list.add("no4");  System.out.println(subList);  for(String str:subList){      System.out.println(str);  }}

结果如下:

Exception in thread "main" java.util.ConcurrentModificationException  at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1231)  at java.util.ArrayList$SubList.listIterator(ArrayList.java:1091)  at java.util.AbstractList.listIterator(AbstractList.java:299)  at java.util.ArrayList$SubList.iterator(ArrayList.java:1087)  at java.util.AbstractCollection.toString(AbstractCollection.java:454)  at java.lang.String.valueOf(String.java:2994)  at java.io.PrintStream.println(PrintStream.java:821)  at com.jd.cyclePredict.Test.main(Test.java:22)

# 原因分析:- subList操作后会返回基于原数据对象的一个偏移量数据,创建一个新的对象SubList,如图所示:![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2f7fe149002b43e99c07dbf83702c3ee~tplv-k3u1fbpfcp-watermark.image?)- 该对象是ArrayList的一个内部类,存储了原列表的一个偏移量,并且直接把原对象的modCount赋值给了内部类SubList的modCount,但针对原列表list的操作,该内部类是无感知的如下图所示:![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/57f6b3114c504dfd937c24018add648f~tplv-k3u1fbpfcp-watermark.image?)- 当遍历或操作内部类SubLIst时,会针对该类的modCount做一个check如图所示![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e960773752ad4faeae672d818c6c5cd8~tplv-k3u1fbpfcp-watermark.image?)- 如果sublist的modCount和原modCount不一致,会抛ConcurrentModificationException异常;![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6576ebb6fcf54b068df47194de7f0b64~tplv-k3u1fbpfcp-watermark.image?)# 解决办法**一行代码**:

List subList=new ArrayList<>(list.subList(0,1));

![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4d137533388241a48dd1881954e6d0e1~tplv-k3u1fbpfcp-watermark.image?)# 总结:- **截取操作后如果不需要原对象则可以进行该操作,但需求变更或者其他可能会导致后面有这么操作引起不必要的麻烦;**- **如果截取后有后续操作,建议创建一个新对象**
原文:https://juejin.cn/post/7100508447992446989


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/java/15889.html