Java中的Iterator迭代器与fail-fast属性

本文详细解读了Java中的Iterator模式,介绍了fail-fast机制如何防止并发修改异常,并通过实例展示了ArrayList中Iterator的实现及其在多线程和单线程场景下的fail-fast触发。同时涵盖了ListIterator的特性与应用。
摘要由CSDN通过智能技术生成

什么是迭代器模式

迭代器模式(Iterator),提供一种方法访问集合内的元素并且不用了解该集合的内部细节。
这样使得对集合的遍历操作与具体的底层实现相隔离。

Iterator接口与fail-fast机制

在Iterator接口有四个方法:

boolean hasNext():如果还有元素可以进行迭代,返回trueE next():返回迭代的下一个元素。
void remove():移除迭代器返回的最后一个元素。
void forEachRemaining():对集合中剩余的元素进行操作,直至元素完毕或抛出异常。

fail-fast机制是java集合中的一种错误机制。当多个线程对同一个集合内容进行操作时,就可能产生fail-fast事件。如:当多个线程对集合进行操作时,若其中一个线程通过Iterator遍历集合时,该集合内容被其他线程改变,就会抛出异常。
不止多线程,单线程也会出现fail-fast事件

ArrayList的Iterator实现

在ArrayList通过内部类Itr实现Iterator接口
在这里插入图片描述
在Itr类中有三个变量:

 int cursor;  //下一个元素的索引位置
 int lastRet = -1; //上一个返回的元素的索引位置
 //预期被修改次数,其中modCount表示列表结构被修改的次数,
 //当列表内部结构发生改变时(add,set,remove)时,modCount+1
 int expectedModCount = modCount; 

看看具体的方法:

  • hasNext()
 public boolean hasNext() {
 //判断下一个元素的索引是否等于集合的大小
	return cursor != size;
 }
  • next()
public E next() {
	//调用checkForComodification方法判断expectedModCount是否等于modCount
	checkForComodification();
	int i = cursor;
	if (i >= size) //元素索引超出边界
		throw new NoSuchElementException();
	Object[] elementData = ArrayList.this.elementData; //ArrayList的底层数组
	if (i >= elementData.length)
		throw new ConcurrentModificationException();
	 cursor = i + 1;
	return (E) elementData[lastRet = i];
}

checkForComodification方法:

//判断expectedModCount是否等于modCount
final void checkForComodification() {
	if (modCount != expectedModCount)
		throw new ConcurrentModificationException();
}
  • remove()
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();
	}
}

ArrayList下触发fail-fast机制

多线程:

public class fail_fastTest {

	public static void main(String[] args) {
		List<Integer> list = new ArrayList<>();
		list.add(1);
		list.add(2);
		list.add(3);
		Thread thread1 = new Thread() {
			@Override
			public void run() {
				Iterator<Integer> iterator = list.iterator();
				while (iterator.hasNext()) {
					System.out.println(iterator.next());
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			};
		};

		Thread thread2 = new Thread() {
			@Override
			public void run() {
				try {
					Thread.sleep(300);
					list.add(4);// 修改集合
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		};

		thread1.start();
		thread2.start();

	}

}

结果:
在这里插入图片描述
只输出两个数字就会报ConcurrentModificationException错误。

单线程:

public class fail_fastTest {

	public static void main(String[] args) {
		List<Integer> list = new ArrayList<>();
		list.add(1);
		list.add(2);
		list.add(3);
		Iterator<Integer> iterator=list.iterator();
		while(iterator.hasNext()) {
			System.out.println(iterator.next());
			list.add(4);
		}
	}

}

结果:
在这里插入图片描述

ListIterator

ListIterator继承于Iterator接口,只能用于各种List类型的访问。它比Iterator接口方法更多。

boolean hasNext();  //正向遍历,如果还有迭代元素返回true
E next();  //下一个迭代元素
boolean hasPrevious(); //逆向遍历,如果还有迭代元素返回true
E previous(); //前一个迭代元素
int previousIndex(); //返回对previous后续调用所返回元素的索引
void remove();  //移除由迭代器返回的最后一个元素
void set(E e);  //用指定元素替换迭代器返回的最后一个元素
void add(E e);  //将指定的元素插入集合
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值