方法:
while(iterator.hasNext()){
String s = (String) iterator.next();
if(s.contain("a))
iterator.remove();
}
Collection集合:Iterator iterator()方法
ArrayList arr = new ArrayList();
Iterator iterator = arr.iterator();
while(iterator.hasNext){
System.out.println(iterator.next());
}
【java.lang.Iterable接口】:
【java.util.Iterator接口】
//jdk1.8以后removeIf()
coll.removeIf(new Predicate(){
@Override
public bollean test(Object o) {
return (String(o)).contains("o");
}
});
//2、Iterator迭代时remove()方法:
Collection coll = new ArrayList();
coll.add("hihi");
coll.add("hello");
coll.add("world");
coll.add("zhang");
coll.add("san");
Iterator iterator = coll.iterator();
while (iterator.hasNext()){
String s = (String) iterator.next();
if(s.contains("o")){
iterator.remove();
//coll.remove(s);//.ConcurrentModificationException
}
}
System.out.println(coll);
//在foreach循环时删除
for (Object o : coll) {
if(((String) o).contains("a")){
coll.remove(o);//ConcurrentModificationException
}
}
System.out.println(coll);
【Iterator原理】
Iterator对象迭代元素的过程:
【ArrayList里面源码分析】:
public Iterator<E> iterator() {
return new Itr();
}
创建了一个Iterator迭代器对象,返回ArrayList类中的Itr内部类,Itr内部类实现了Iterator接口。
private class Itr implements Iterator<E> {
int cursor; // 游标,指定当前集合索引
int lastRet = -1; // 返回上一次遍历元素的索引,如果不存在为-1
int expectedModCount = modCount;//迭代器创建时的modCount值
Itr() {}
在ArrayList里,发现modCount变量定义在ArrayList的父类AbstractList里。在涉及add新增、remove删除、fastRemove、clear等会改变集合结构的操作,都会通过modCount++形式,增加列表在结构上被修改的次数。
//AbstractList.java
protected transient int modCount = 0;
modCount是这个list被结构性修改的次数。子类使用这个字段是可选的,如果子类希望提供fail-fast迭代器,它仅仅需要在add(int, E),remove(int)方法(或者它重写的其他任何会结构性修改这个列表的方法)中添加这个字段。调用一次add(int,E)或者remove(int)方法时必须且仅仅给这个字段加1,否则迭代器会抛出伪装的ConcurrentModificationExceptions错误。如果一个实现类不希望提供fail-fast迭代器,则可以忽略这个字。
public boolean hasNext() {
return cursor != size;
}
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();
}
康康remove(o)
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 void fastRemove(int index) {
modCount++;
......
}
【总结】:Iterator如何实现fail-fast机制的?
fail-fast产生的原因:在于程序在遍历过程中,某个线程对该 collection 在结构上对其做了修改,此时迭代器抛出 ConcurrentModificationException 异常信息,导致遍历失败,从而产生 fail-fast。由此可以看出fail-fast不允许在遍历的过程中对容器中的数据进行修改。
但是该异常不会始终指出对象已经由不同线程并发修改,如果单线程违反了规则,同样也有可能会抛出改异常。不能保证一定会出现该错误,但是快速失败操作会尽最大努力抛出ConcurrentModificationException异常,所以因此,为提高此类操作的正确性而编写一个依赖于此异常的程序是错误的做法,正确做法是:ConcurrentModificationException 应该仅用于检测 bug。