Iterator遍历器删除集合中元素抛异常
来源:互联网 发布:信仰的定义知乎 编辑:程序博客网 时间:2024/06/05 18:56
一、我们知道遍历集合的过程中,安全的移除集合中的元素,要使用遍历器Iterator以及其remove()方法。但是有的时候貌似并不好用
二、示例(这里只列举了一种,其他很多集合也存在同样的坑)
import java.util.*;public class MyTest { public static void main(String [] args) { try { String str = "abc,def,hig"; List<String> oTestList = Arrays.asList(str.split(",")); Iterator<String> oIterator = oTestList.iterator(); while (oIterator.hasNext()) { if ("def".equals(oIterator.next())) { oIterator.remove(); } } } catch (Exception e) { e.printStackTrace(); } }}
异常结果:
java.lang.UnsupportedOperationException
at java.util.AbstractList.remove(AbstractList.java:161)
at java.util.AbstractList$Itr.remove(AbstractList.java:374)
at com.glodon.gccs.test.MyTest.main(MyTest.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
三、原因分析
1、每个集合调用iterator()生成的遍历器实际上都是在该集合中定义的一个Iterator的子类,执行remove()方法,也就是执行该子类中的remove()方法,下面从源码中分析,坑从何来?
2、源码跟踪
1)Arrays.asList()
@SafeVarargs @SuppressWarnings("varargs") public static <T> List<T> asList(T... a) { return new ArrayList<>(a); }
注意:这个ArrayList并不是java.util中的,而是Arrays中自定义的
private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable { private static final long serialVersionUID = -2764017481108945198L; private final E[] a; ArrayList(E[] array) { a = Objects.requireNonNull(array); } @Override public int size() { return a.length; } @Override public Object[] toArray() { return a.clone(); } @Override @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { int size = size(); if (a.length < size) return Arrays.copyOf(this.a, size, (Class<? extends T[]>) a.getClass()); System.arraycopy(this.a, 0, a, 0, size); if (a.length > size) a[size] = null; return a; } @Override public E get(int index) { return a[index]; } @Override public E set(int index, E element) { E oldValue = a[index]; a[index] = element; return oldValue; } @Override public int indexOf(Object o) { E[] a = this.a; if (o == null) { for (int i = 0; i < a.length; i++) if (a[i] == null) return i; } else { for (int i = 0; i < a.length; i++) if (o.equals(a[i])) return i; } return -1; } @Override public boolean contains(Object o) { return indexOf(o) != -1; } @Override public Spliterator<E> spliterator() { return Spliterators.spliterator(a, Spliterator.ORDERED); } @Override public void forEach(Consumer<? super E> action) { Objects.requireNonNull(action); for (E e : a) { action.accept(e); } } @Override public void replaceAll(UnaryOperator<E> operator) { Objects.requireNonNull(operator); E[] a = this.a; for (int i = 0; i < a.length; i++) { a[i] = operator.apply(a[i]); } } @Override public void sort(Comparator<? super E> c) { Arrays.sort(a, c); } }
可以看到,该类继承了AbstractList,而自身并未实现任何遍历器相关的方法,所以在使用这个集合进行遍历器相关操作,实际上是调用AbstractList相关的遍历器操作。
2)AbstractList iterator()
public Iterator<E> iterator() { return new Itr(); }
3)AbstractList iterator的remove()
public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { AbstractList.this.remove(lastRet); if (lastRet < cursor) cursor--; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } }
注意这行代码:AbstractList.this.remove(lastRet);
iterator的remove()实际是调用AbstractList自身的remove()方法
4)AbstractList remove()
public E remove(int index) { throw new UnsupportedOperationException(); }
是不是很坑?
四、总结:集合使用遍历器进行安全移除元素时,一定要确保:
1)该集合是否重写了遍历器,重写的遍历器是否支持移除操作;
2)若集合未重写遍历器,其基类的遍历器操作是否可正常使用
经验之谈:JDK源码中不推荐直接使用的基类,通常都会在相应方法中抛异常,促使开发人员使用相应子类进行开发
- Iterator遍历器删除集合中元素抛异常
- Java集合中删除元素使用Iterator
- Iterator 在迭代中删除元素抛异常
- Iterator迭代器遍历集合元素
- 利用Iterator删除集合元素
- 循环遍历中删除集合的元素
- 如何在遍历中使用 iterator/reverse_iterator 删除元素
- 如何在遍历中使用 iterator/reverse_iterator 删除元素
- 每天进步一点点_遍历集合删除元素的异常
- Java list集合通过遍历删除元素异常分析
- Iterator遍历集合时不可以删除集合中的元素问题
- 集合中遍历元素并删除个别元素
- 集合遍历过程中删除集合元素问题
- 如何边遍历集合边删除元素--使用Iterator中的remove()方法
- STL中 如何在遍历中使用 iterator/reverse_iterator 删除元素
- java遍历集合删除特定元素的 java.util.ConcurrentModificationException异常
- 使用iterator删除list,map中元素
- 通过Iterator来遍历集合的元素(一)
- dagger2学习
- hdu 6216 A Cubic number and A Cubic Number
- Java并发编程:volatile关键字解析
- StratoIO WebPrinter 是什么?StratoIO WebPrinter实现打印的过程,StratoIO WebPrinter Javascript API
- CDH 安装spark后,spark-shell启动报错
- Iterator遍历器删除集合中元素抛异常
- 使用Anaconda与pip报错'_NamespacePath' object has no attribute 'sort'的解决方法
- 计蒜客 16957 Skiing(2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 H)
- SparkStream:4)foreachRDD详解
- Hive 连接查询JOIN
- MyBatis集成Spring事务管理
- update select set
- 微信浏览器无法使用reload()刷新页面 gif图兼容性
- scikit-learn 梯度提升树(GBDT)调参小结