如何解决这个问题 java.util.arraylistConcurrentModificationException

标签:至少1个,最多5个
今天在遍历arrayList的时候,添加了一些元素进去,然后抛出ConcurrentModificationException 这个异常。然后就去网上找了下资料,抛出这个异常的原因是因为,list 集合 在遍历的时候是不允许修改list的。实质是不允许修改当前遍历list的长度的。
在 arrayList 和 linkedList 的实现里 都一个 modCount 这个遍历。 对于arrayList,在调用remove 和 clean 方法的时候,会修改 modCount 这个变量的值。在遍历的时候这个值被修改了。就会报错。 但我是对arrayList 添加元素。并不是删除,按理来说是不会修改modCount 这个值的。 可还是报错了。后来查看了源码。arrayList是用数组实现的。当你添加元素的时候,实现是会去检查数组的大小,是否需要扩容。问题就在这里,在扩容的时候,是会修改modCount 这个值的。
public boolean add(E e) {
ensureCapacityInternal(size + 1);
// Increments modCount!!
次方法用来检查是否要扩大数组的大小
elementData[size++] =
private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ELEMENTDATA) {
// 加入 数组还是为空话,选择默认的大小
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
//扩大数组的大小
ensureExplicitCapacity(minCapacity);
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
传入进来的容量必须大于当前的容量
if (minCapacity - elementData.length & 0)
grow(minCapacity);
对于linkedList 的话
你调用add 方法的时候就直接修改modCount 的值了。 因为linkedList是用链表实现的。所以每一次添加其实都是在修改集合的大小。
private void linkFirst(E e) {
final Node&E& f =
final Node&E& newNode = new Node&&(null, e, f);
first = newN
if (f == null)
last = newN
f.prev = newN
modCount++;
那我们需要就是要修改大小怎么办呢?对于 删除元素的话,我们可以用迭代器,然后使用迭代器的 remove 的方法。这个是对于删除来说比较通用的方法。
假如是要添加元素的的话。我没有找到很好的方法。我是用另外要给list 暂时存放需要的添加的元素。等遍历完以后,再把,需要添加的元素一起放进去。不知哪位高人有更好的方法。
0 收藏&&|&&0
你可能感兴趣的文章
3 收藏,425
20 收藏,1.1k
6 收藏,1.4k
分享到微博?
我要该,理由是:2007年5月 其他开发语言大版内专家分月排行榜第二
2007年5月 其他开发语言大版内专家分月排行榜第二
2008年2月 总版技术专家分月排行榜第一2008年1月 总版技术专家分月排行榜第一
2008年7月 总版技术专家分月排行榜第三2008年6月 总版技术专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。174268人阅读
java(55)
在使用iterator.hasNext()操作迭代器的时候,如果此时迭代的对象发生改变,比如插入了新数据,或者有数据被删除。
则使用会报以下异常:
java.util.ConcurrentModificationException
&&&&&&& at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
&&&&&&& at java.util.HashMap$KeyIterator.next(HashMap.java:828)
例如以下程序(转自互联网):mport java.util.*;
public class Main
public static void main(String args[])
Main main = new Main();
main.test();
public void test()
Map bb = new HashMap();
bb.put(&1&, &wj&);
bb.put(&2&, &ry&);
Iterator it = bb.keySet().iterator();
while(it.hasNext()) {
Object ele = it.next();
bb.remove(ele);
System.out.println(&Success!&);
原因:Iterator做遍历的时候,HashMap被修改(bb.remove(ele), size-1),Iterator(Object ele=it.next())会检查HashMap的size,size发生变化,抛出错误ConcurrentModificationException。
解决办法:
1) 通过Iterator修改Hashtable
while(it.hasNext()) {
Object ele = it.next();
&&&&&&&&&&& it.remove();
2) 根据实际程序,您自己手动给Iterator遍历的那段程序加锁,给修改HashMap的那段程序加锁。
3) 使用“ConcurrentHashMap”替换HashMap,ConcurrentHashMap会自己检查修改操作,对其加锁,也可针对插入操作。
import java.util.concurrent.*;
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:515630次
积分:4268
积分:4268
排名:第7997名
原创:74篇
转载:78篇
评论:14条
(5)(1)(2)(4)(3)(5)(2)(6)(3)(2)(6)(2)(1)(4)(5)(4)(2)(2)(5)(4)(1)(1)(3)(2)(2)(1)(6)(6)(1)(1)(1)(2)(3)(6)(2)(2)(3)(2)(4)(1)(4)(1)(9)(2)(5)(2)(4)(1)(3)(1)(1)(1)(1)(1)
(window.slotbydup = window.slotbydup || []).push({
id: '4740887',
container: s,
size: '250,250',
display: 'inlay-fix'17被浏览2962分享邀请回答List&String& list = new ArrayList&String&();
list.add("a");
List&String& subList = list.subList(0, 1);
subList.add("b");
System.out.println(list);
System.out.println(subList);
输出结果是两个[a, b]SubList中没有数组,这就意味着你向SubList中添加元素的话,会添加到名叫list的ArrayList中,所以输出list的结果里面有b。来看SubList的add方法实现:第三行向list中添加元素,这将会导致list中的modCount变量加1,然后第4行,将subList的modCount等于list的modCount,所以添加完成后两个modCount是一样的吧。但是把代码换成下面这样就不行了List&String& list = new ArrayList&String&();
list.add("a");
List&String& subList = list.subList(0, 1);
list.add("b");
System.out.println(list); // [a,b]
System.out.println(subList); // java.util.ConcurrentModificationException
list.add("b")会把“b”放入数组中(不用担心数组大大小问题,它会自己扩容的),然后把list的modCount加1,subList中的modCount还是那么大(因为list根本就不知道subList的存在对吧)。对subList进行迭代的时候,首先会创建出一个迭代器,也就是说会执行下面的代码:所以它就把异常扔出去了~~232 条评论分享收藏感谢收起博客分类:
:在list&String& 中清空所有的记录,只使用使用单循环,不使用removeAll()
可以写出五种方式,代码如下:
import java.util.ArrayL
import java.util.I
import java.util.L
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();
for (String str : list) {
list.remove(str);
} catch (Exception e) {
// java.util.ConcurrentModificationException
e.printStackTrace();
System.out.println("-2-使用Iterator的remove");
list = test.buildList();
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");
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");
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()操作,所以不会出现这种异常。
:在执行remove()不要将ArrayList 与Interator混合使用,单独使用Interator以及ArrayList的删除都是OK的
6参考的源码
Iterator的next()方法:
public E next() {
checkForComodification();
if (i &= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementD
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();
ArrayList.this.remove(lastRet);
cursor = lastR
lastRet = -1;
//当执行remove操作后,将改变的modCount值重新赋给expectedModCount
expectedModCount = modC
} 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 & index++)
if (elementData[index] == null) {
fastRemove(index);
for (int index = 0; index & index++)
if (o.equals(elementData[index])) {
fastRemove(index);
* 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] = // Let gc do its work
浏览 17793
浏览: 101373 次
来自: 深圳
提供下第六种做法,多用些内存,遍历set的时候,用list删除 ...
spring 2.5
我已经更新了,现在是完整版了。请到csdn上下载,或者向我要。 ...
好,英文差有中文的先学学
Service 确实
不过为什么没有得到广泛应用呢 !求教
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'

我要回帖

更多关于 java.util.list 的文章

 

随机推荐