本文共 2574 字,大约阅读时间需要 8 分钟。
集合框架:用于存储数据的容器,集合框架是为表示和操作集合而规定的一种统一的标准的体系结构,集合包含三大块内容:
集合的特点主要有如下两点:
Map接口和Collection接口是所有集合框架的父接口:
fail-fast机制,即快速失败机制,是Java集合中的一种错误检测机制。当在迭代集合过程中该集合在结构上发生改变的时候,就有可能发生fail-fast,即抛出ConcurrentModificationException异常
fail-fast原理:fail-fast是如何抛出ConcurrentModificationException异常的呢?我们知道,对于集合如list,map类,我们都可以通过迭代器来遍历,而iterator其实只是一个接口,如在ArrayList中,当调用list.iterator()时,其源码是:
public Iteratoriterator() { return new Itr(); }
即它会返回一个新的Itr类,而Itr类是ArrayList的内部类,实现了Iterator接口,其中在Itr类中有三个属性:
int cursor;int lastRet=-1;int expectedModCount=modCount;
其中cursor是指集合遍历过程中的即将遍历的元素的索引,lastRet等于cursor-1,默认为-1(表示不存在上一个时,为-1),expectedModCount就是快速失败机制的关键变量了,它初始值为ArrayList中的modCount(因为ArrayList是抽象类AbstractList中的子类,ArrayList也有这个变量,modCount用于记录集合操作过程中的修改次数)
让我们看一下next()方法,看看为什么在迭代过程中,如果有线程对集合结构做出改变,就会发生fail-fast: 我们会发现,每次调用next()方法,在实际访问元素前,都会调用checkForComodification方法,该方法的源代码如下: 当modCount不等于expectedModCount时就会抛出异常,我们知道expectedModCount的默认初始值为modCount,它在遍历过程中不会在发生改变,所以有可能发生改变的只有modCount,当我们对集合进行add,remove,clear等涉及到集合中的元素个数的操作时,modCount就会发生改变,所以在遍历过程中,我们调用相关方法使集合个数发生改变,就会触发fail-fast异常 避免fail-fast的解决方案:Iterator接口提供遍历任何Collection的接口。我们可以从一个Collection中使用迭代器方法来获取迭代器实例,Iterator使用代码如下;
Listlist=new ArrayList<>();Iterator it=list.iterator();
迭代器只能单向遍历,但是更加安全,因为它可以确保,在当前遍历的集合元素被更改的时候,就会抛出ConcurrentModificationException异常
边遍历边修改Collection的唯一正确方法是使用迭代器提供的操作Iterator.remove()方法,不能使用Collection提供的remove方法,因为会触发fail-fast机制,抛出ConcurrentModificationExcepction异常
转载地址:http://umjmb.baihongyu.com/