List如何在增加元素的同时删除元素。 这还不简单? 直接上代码: 然后兴奋的运行程序,结果发现Exception 。 发生了什么错误? 查看ArrayList的add方法: 首先modCount进行了自增然后调用了自己的private void add(E e, Object[] elementData, int s)方法。 其实就是首先判断是否需要扩容,然后将值添加到数组中,数组大小加1。 定位到remove(Object o)方法: 最后调用了fastRemove(Object[] es, int i)方法。 我们又发现了modCount进行了自增,于是我们得知modCount其实就是修改的次数,add和remove包括clear,addAll等对list元素的操作都会调用它。 现在回到我们代码报错的地方 发现checkForComodification处抛出了异常。 我们发现是因为判断modCount和expectedModCount不相等于是抛出了异常。 源码中发现初始化时expectedModCount=modCount 迭代时调用next方法 也是先调用checkForComodification()方法modCount != expectedModCount则抛出异常。 刚才我们发现了remove方法会调用fastRemove方法 之后modCount会进行自增,而expectedModCount没有进行改变,两者不相等则抛出ConcurrentModificationException()异常。 利用Iterator迭代器删除即可 因为Iterator的remove方法会使expectedModCoun和modCount两值相等,自然没问题了。 运行结果: 那就是ArrayList 本身不是线程安全的
问题介绍
List<String> lists = new ArrayList<>(); lists.add("MRyan"); lists.add("MRyan2"); lists.add("MRyan3"); for (String list : lists) { if (list.equals("MRyan")) { lists.remove(list); } } System.out.println(lists);
很惨,报错了,报了如下错误:Exception in thread "main" java.util.ConcurrentModificationException at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1012) at java.base/java.util.ArrayList$Itr.next(ArrayList.java:966) at com.text.text.main(text.java:18)
报错原因及分析源码
java.util.ConcurrentModificationException表示ArrayList在迭代的时候如果同时对其进行修改就会抛出的异常。
也就是说这是一个并发的问题。
那为什么会发生这个错误?
接下来我们来从源码下手:
定位到ArrayList的源码 /** * Appends the specified element to the end of this list. * * @param e element to be appended to this list * @return {@code true} (as specified by {@link Collection#add}) */ public boolean add(E e) { modCount++; add(e, elementData, size); return true; }
定位到private void add(E e, Object[] elementData, int s)方法 /** * This helper method split out from add(E) to keep method * bytecode size under 35 (the -XX:MaxInlineSize default value), * which helps when add(E) is called in a C1-compiled loop. */ private void add(E e, Object[] elementData, int s) { if (s == elementData.length) elementData = grow(); elementData[s] = e; size = s + 1; }
那你会有疑问了,刚才出现的modCount是什么?别着急往下看 /** * 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 * {@code i} such that * {@code Objects.equals(o, get(i))} * (if such an element exists). Returns {@code true} 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 {@code true} if this list contained the specified element */ public boolean remove(Object o) { final Object[] es = elementData; final int size = this.size; int i = 0; found: { if (o == null) { for (; i < size; i++) if (es[i] == null) break found; } else { for (; i < size; i++) if (o.equals(es[i])) break found; } return false; } fastRemove(es, i); return true; }
定位到fastRemove(Object[] es, int i)/** * Private remove method that skips bounds checking and does not * return the value removed. */ private void fastRemove(Object[] es, int i) { modCount++; final int newSize; if ((newSize = size - 1) > i) System.arraycopy(es, i + 1, es, i, newSize - i); es[size = newSize] = null; }
Exception in thread "main" java.util.ConcurrentModificationException at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1012) at java.base/java.util.ArrayList$Itr.next(ArrayList.java:966) at com.text.text.main(text.java:18)
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }
那么问题又来了。
expectedModCount是什么??? /** * An optimized version of AbstractList.Itr */ private class Itr implements Iterator<E> { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; // prevent creating a synthetic constructor Itr() {} public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") 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]; } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } @Override public void forEachRemaining(Consumer<? super E> action) { Objects.requireNonNull(action); final int size = ArrayList.this.size; int i = cursor; if (i < size) { final Object[] es = elementData; if (i >= es.length) throw new ConcurrentModificationException(); for (; i < size && modCount == expectedModCount; i++) action.accept(elementAt(es, i)); // update once at end to reduce heap write traffic cursor = i; lastRet = i - 1; checkForComodification(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
expectedModCount表示的是ArrayList修改次数的期望值@SuppressWarnings("unchecked") 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]; }
如何解决此问题
public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { SubList.this.remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = SubList.this.modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } }
正确代码: List<String> lists = new ArrayList<>(); lists.add("MRyan"); lists.add("MRyan2"); lists.add("MRyan3"); Iterator<String> iterator=lists.iterator(); while(iterator.hasNext()){ String list=iterator.next(); if(list.equals("MRyan")){ iterator.remove(); } } System.out.println(lists);
[MRyan2, MRyan3]总结
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算