- 浏览: 136044 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
jptiancai:
提供下第六种做法,多用些内存,遍历set的时候,用list删除 ...
解决ArrayList的ConcurrentModificationException -
langmanjian0212:
spring 2.5
spring中文文档下载 -
hoarhoar:
我已经更新了,现在是完整版了。请到csdn上下载,或者向我要。 ...
java编程思想第四版勘误下载 -
zzplovejava:
好,英文差有中文的先学学
spring中文文档下载 -
呆哥儿:
Service 确实 不过为什么没有得到广泛应用呢 !求教
使用泛型类简化服务层(Service)类的设计
1 问题 :在list<String> 中清空所有的记录,只使用使用单循环,不使用removeAll()
2 可以写出五种方式,代码如下:
import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class ListRemoveTest { public static void main(String[] args) { ListRemoveTest test = new ListRemoveTest(); System.out.println("-1-使用jdk5.0以后的增强for循环去remove"); List<String> list = test.buildList(); try { for (String str : list) { list.remove(str); } } catch (Exception e) { // java.util.ConcurrentModificationException e.printStackTrace(); } System.out.println("-2-使用Iterator的remove"); list = test.buildList(); try { Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { iterator.next(); iterator.remove(); } } catch (Exception e) { // java.lang.IllegalStateException e.printStackTrace(); } System.out.println("-3-iterator遍历+list的remove"); try { list = test.buildList(); for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) { String str = (String) iterator.next(); list.remove(str); } } catch (Exception e) { // java.util.ConcurrentModificationException e.printStackTrace(); } System.out.println("-4-使用list的remove(int)方法. [由后向前删除]"); list = test.buildList(); for (int i = list.size(); i > 0; i--) { list.remove(i - 1); } System.out.println("-5-使用list的remove(int)方法. [由前向后删除]"); list = test.buildList(); for (int i = 0; i < list.size(); i++) { list.remove(0); } } private List<String> buildList() { List<String> list = new ArrayList<String>(); list.add("a"); list.add("b"); list.add("c"); return list; } }
3运行结果如下:
-1-使用jdk5.0以后的增强for循环去remove java.util.ConcurrentModificationException -2-使用Iterator的remove -3-iterator遍历+list的remove at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:781) at java.util.ArrayList$Itr.next(ArrayList.java:753) at com.jdk.ListRemoveTest.main(ListRemoveTest.java:14) java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:781) at java.util.ArrayList$Itr.next(ArrayList.java:753) at com.jdk.ListRemoveTest.main(ListRemoveTest.java:39) -4-使用list的remove(int)方法. [由后向前删除] -5-使用list的remove(int)方法. [由前向后删除]
2,4,5运行正常,1,3抛出
java.util.ConcurrentModificationException
4问题原因:
1,3都是因为list的长度改变,Iterator执行next()方法时,调用checkForComodification()时出错,1,3是同一个问题,这两个方法remove操作都是执行的是ArrayList中的remove方法,根本原因在于expectedModCount与modCount他们的不相等,由于执行了ArrayList中的remove(),modCount在每一次循环值会发生改变,而expectedModCount并没有发生,在执行checkForComodification()方法就会抛出异常。
2之所以正确运行是因为调用了Iterator的remove方法,4,5不会执行checkForComodification()操作,所以不会出现这种异常。
5结论 :在执行remove()不要将ArrayList 与Interator混合使用,单独使用Interator以及ArrayList的删除都是OK的
6参考的源码
Iterator的next()方法:
public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }
Iterator的remove()方法:
public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.remove(lastRet); cursor = lastRet; lastRet = -1; //当执行remove操作后,将改变的modCount值重新赋给expectedModCount expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } }
ArrayList的remove()方法:
/** * Removes the first occurrence of the specified element from this list, * if it is present. If the list does not contain the element, it is * unchanged. More formally, removes the element with the lowest index * <tt>i</tt> such that * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt> * (if such an element exists). Returns <tt>true</tt> if this list * contained the specified element (or equivalently, if this list * changed as a result of the call). * * @param o element to be removed from this list, if present * @return <tt>true</tt> if this list contained the specified element */ public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } /* * Private remove method that skips bounds checking and does not * return the value removed. */ private void fastRemove(int index) { //此处modCount发生了改变,但expectedModCount仍然未发生变化,所以再执行下一次循环时执行 //Interator的next()方法当然会报错 modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // Let gc do its work }
评论
3 楼
jptiancai
2016-02-02
提供下第六种做法,多用些内存,遍历set的时候,用list删除
System.out.println("-6-使用set");
Set<String> s = new HashSet<String>();
s.addAll(list);
for (String str : s) {
list.remove(str);
}
System.out.println("-6-使用set");
Set<String> s = new HashSet<String>();
s.addAll(list);
for (String str : s) {
list.remove(str);
}
2 楼
Arron.li
2010-04-16
首先非常感谢一楼的建议,自己确实对这个数据结构的本质理解的不够深刻,我会继续认真分析这个数据结构,希望读者多提您的建议和参考。
1 楼
sdh5724
2010-04-16
虽然说对了现象, 也规避了现象。问题分析的角度完全不对。 关键还是要理解这个数据结构构建的原理。 ConcurrentModificationException 这错误本身是为“提醒”程序员并发修改数据结构使用的, 因为这个不是写线程安全的数据结构, 不是为了这个循环删除的目的。从本质上去理解, 你会轻松很多。
发表评论
-
毕业两年我学到了什么
2010-06-04 14:34 1289明天就要离开我现在的 ... -
java反射机制与动态代理
2010-06-02 16:42 17101 java反射机制:运行时的类信息 Class类与java ... -
浅析java回调机制与观察者模式
2010-06-02 10:38 42211 java回调机制: 首先解释java回调机制,对象能够携 ... -
java编程思想第四版勘误下载
2010-05-25 17:08 1242此文档是在CSDN下载的,提供javaeye社区下载 -
java泛型通配符-协变与逆变
2010-05-24 12:36 5682周末研究了下java泛型,关于泛型通配符的协变与逆变问题,题目 ... -
java反射机制-通过非默认构造器创建对象
2010-05-21 12:27 3631今天研究了下java反射机制,并利用反射机制,通过非默认构造器 ... -
浅谈非静态内部类不能有静态成员
2010-05-05 23:09 41571 非静态内部类为什么不能有静态成员,我自己总结了下, 如下 ... -
类的初始化顺序
2010-05-02 10:39 11961 对于继承来讲,初始化次序大致如下: 1)父类的静态变量和 ... -
日期的加减法
2010-03-24 15:30 1872今天小试了日期的加减法,功能实现了,但觉得代码很长,有更好的解 ... -
JDK1.5 新特性
2009-07-08 11:12 878"JDK1.5"的一个重要主题就是通过新增 ... -
JAVA反射机制的学习
2009-07-07 14:07 1100原文:http://www.iteye.com/t ... -
JAVA多线程
2009-07-02 14:14 993原文出处:http://www.iteye.com/topic ... -
java虚拟机的类装载
2009-06-25 17:19 822原文出处:http://webservices.ctocio. ... -
JAVA面试试题解惑系列(创建几个String对象)
2009-06-22 15:33 1147作者:臧圩人(zangweiren) 网址:http:/ ... -
JAVA面试题解惑系列(类的初始化顺序)
2009-06-22 10:57 848网址:http://zangweiren.iteye.com ... -
java参数传递总结
2008-12-13 12:53 946以前学习C的 时候参数传递的方式有两种,一种叫"值传 ...
相关推荐
bject[initialCapacity]; } else if (initialCapacity == 0) {...同时,需要注意在并发环境下使用ArrayList可能会遇到`ConcurrentModificationException`,应当避免在遍历过程中修改集合,或者选择线程安全的数据结构。
这个示例代码尝试在遍历 ArrayList 时删除其中的一个元素,这将导致 ConcurrentModificationException 异常。 那么,为什么会抛出这个异常呢?我们可以通过查看 ArrayList 的源码来了解原因。ArrayList 的 iterator...
如果多个线程同时修改ArrayList,可能会导致数据不一致或抛出ConcurrentModificationException。若需在多线程环境中使用,可以考虑使用Collections.synchronizedList对ArrayList进行包装,或者使用线程安全的...
《深入解析ArrayList》 ArrayList是Java集合框架中常用的列表实现之一,它继承自AbstractList,并实现了List接口。本文将从ArrayList的源码出发,详细解析其底层实现、默认初始容量、RandomAccess接口以及添加和...
在使用时,另一个线程改变了 Vector,那么将会抛出 ConcurrentModificationException 异常。因此,如果多线程并发访问 Vector,通常需要通过 synchronized 关键字进行同步控制。 HashMap 类 HashMap 是一个散列表,...
老猿说说-ArrayList MD文件 1. 所有的操作都是线程安全的,我们在使用时,无需再加锁; 2. 多个线程同时进行put、remove等操作时并不会阻塞,可以同时进行,和HashTable不同,HashTable在操作时,会锁住整个Map; 3. ...
如果在迭代过程中有其他线程修改了ArrayList的结构,则迭代器会抛出`ConcurrentModificationException`异常。这一机制有助于检测并发修改的问题,并提示开发者修复代码。 #### 七、结论 通过深入分析ArrayList的...
在多线程环境下,多个线程同时对ArrayList进行操作(尤其是修改操作,如add、remove等)可能导致数据不一致或抛出`ConcurrentModificationException`。为了使ArrayList在多线程环境下安全使用,可以借助`Collections...
《硬核ArrayList源码分析——深入理解Java集合框架》 ArrayList是Java集合框架中的一个重要组成部分,它是基于动态数组实现的列表。...每天温习ArrayList的源码,无疑能提升我们的编程素养和问题解决能力。
`ConcurrentModificationException`的根源在于`ArrayList`、`LinkedList`等集合类的实现。它们维护了一个迭代器,当检测到在迭代过程中有非迭代器自身的修改操作时,就会抛出此异常。这是为了保护集合的完整性,...
- ArrayList和Vector的迭代器在遍历元素时性能相近,但因为Vector的线程安全性,如果在迭代过程中其他线程修改了Vector,迭代器会抛出`ConcurrentModificationException`,而ArrayList则不会。 6. **使用场景**: ...
- `Iterator`遍历:`Iterator`允许我们在遍历过程中删除元素,而不会导致`ConcurrentModificationException`。它不依赖于索引,因此在某些情况下可能比基于索引的遍历更快。然而,如果只是简单地遍历和访问元素,...
2. **解决办法**: - 使用线程安全的`Vector`替代`ArrayList`。 - 通过`Collections.synchronizedList()`方法将`ArrayList`转换为线程安全的版本。 - 使用`CopyOnWriteArrayList`,它采用写时复制策略,读操作时...
当ArrayList在迭代过程中被修改(例如添加、删除元素),迭代器会立即抛出ConcurrentModificationException,以防止数据的不一致性。这是一种设计模式,用于快速检测并发修改,以避免潜在的错误。 总的来说,...
然而,在遍历 ArrayList 时,如果需要删除某些元素,可能会遇到 ConcurrentModificationException 异常。今天,我们将讨论如何正确地遍历和修改 ArrayList。 遍历 ArrayList 的正确方法 在遍历 ArrayList 时,不能...
使用Iterator的好处是它可以检测并处理并发修改异常(ConcurrentModificationException),这是在遍历集合时尝试修改集合的常见错误。以下是如何使用Iterator遍历ArrayList: ```java ArrayList<String> arrayList ...
- 为了避免并发修改异常(`ConcurrentModificationException`),在多线程环境下使用 ArrayList 时,应使用 `Collections.synchronizedList` 或 `CopyOnWriteArrayList`。 通过了解 ArrayList 的源码,我们可以更好...
`java.util.ConcurrentModificationException` 是一个在 Java 中常见的运行时异常,它通常发生在多线程环境中,当一个线程正在遍历一个集合(如 `ArrayList`, `HashMap` 等),而另一个线程同时尝试修改这个集合时。...
iterator和listIterator方法是快速失败的 :如果列表在任何时间从结构上修改创建迭代器之后,以任何方式,除了通过迭代器自身的remove或add方法,迭代器都将抛出ConcurrentModificationException 。 因此,在并发的...