我是靠谱客的博主 尊敬眼神,最近开发中收集的这篇文章主要介绍在Iterator迭代器中使用iterator的remove方法和集合本身的remove方法删除集合中某个数据的区别,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在迭代循环遍历时删除某个数据,发现以下两种现象:使用集合本身的remove方法会报错,而使用iterator迭代器的remove方法不会出错;

使用集合本身的remove方法:

public class MyList {
public static void main(String[] args) {
List<String>
list=new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");
Iterator<String> iterator=list.iterator();
while(iterator.hasNext()){
String item=iterator.next();
if(item.equals("B")){
list.remove(item);
}
System.out.println(item);
}
}
}

使用list.remove(),会报一个java.util.ConcurrentModificationException的异常错误:
在这里插入图片描述
使用迭代器的remove方法:

public class MyList {
public static void main(String[] args) {
List<String>
list=new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");
Iterator<String> iterator=list.iterator();
while(iterator.hasNext()){
String item=iterator.next();
if(item.equals("B")){
//list.remove(item);
iterator.remove();
}
System.out.println(item);
}
System.out.println(list);
}
}

使用iterator.remove()不会出错;

通过观察源码可知:

在AbstractList的源码中:每一次对集合进行add、set、get、remove操作都会进行一次checkForComodification();校验操作:

public E set(int index, E element) {
rangeCheck(index);
checkForComodification();
return l.set(index+offset, element);
}
public E get(int index) {
rangeCheck(index);
checkForComodification();
return l.get(index+offset);
}
public int size() {
checkForComodification();
return size;
}
public void add(int index, E element) {
rangeCheckForAdd(index);
checkForComodification();
l.add(index+offset, element);
this.modCount = l.modCount;
size++;
}
public E remove(int index) {
rangeCheck(index);
checkForComodification();
E result = l.remove(index+offset);
this.modCount = l.modCount;
size--;
return result;
}

而checkForComodification()方法中的操作是:

 final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}

那modCount和expectedModCount是什么呢?

在ArrayList的源码中可以发现:
在ArrayList中每进行一次remove、add操作,modCount都会加1:

由此可以猜测modCount是保存对集合进行的操作次数的变量;

在迭代器Iterator中,


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;//先将modCount赋值给expectedModCount,保存对集合的操作次数
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;//在此处更新了expectedModCount,所以不会出错
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}

可以发现,modCount存在于AbstractList中,记录集合被修改(add、remove)的次数;在迭代器中,进行list.iterator()时,首先会将修改次数modCount赋值给迭代器中的expectedModCount,用expectedModCount来存储当前集合修改次数;

而如果在迭代循环的过程中:
如果使用了list.remove方法,就会将modCount+1,而后再进行checkForComodification()方法时,就会发现modCount与expectedModCount不相等,就会抛出异常 ConcurrentModificationException;

如果使用了Iterator的remove方法,在Iterator的remove方法中可以发现,它将expectedModCount进行了更新: expectedModCount = modCount;expectedModCount 与modCount相等,就不会报错了;

可以说,迭代器就是当前集合的一个副本

最后

以上就是尊敬眼神为你收集整理的在Iterator迭代器中使用iterator的remove方法和集合本身的remove方法删除集合中某个数据的区别的全部内容,希望文章能够帮你解决在Iterator迭代器中使用iterator的remove方法和集合本身的remove方法删除集合中某个数据的区别所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(80)

评论列表共有 0 条评论

立即
投稿
返回
顶部