AbstractList的有两个内部类实现了迭代器┅个内部类Itr
实现了java的iteratorr
接口,一个内部类ListItr
实现了Listjava的iteratorr
接口后者其实就是前者的升级版罢了,多了一些额外操作
下面先来看一下返回这两个內部类实例的方法的注释:
- 这个方法返回了
java的iteratorr
接口的实现类。backing list我理解是该迭代器持有的外部类对象(list对象)因为Itr
是一个成员内部类,所鉯必然会持有外部类对象而Itr
会调用到size()
,get(int)
, andremove(int)
方法,所以说依赖于它们 - 当遇到并发修改时(比如add、remove),可能抛出runtime exception通过
#modCount
实现,这是外部类对象(list对象)的成员别的线程可能同时也会进行修改动作。
- 可见这个迭代器依赖的操作更多了它还依赖外部类list对象的
set(int, E), add(int, E)
方法。 - 上面注释没讲这个迭代器除了可以往前走
next()
,它还可以往回走previous()
这就上源码分析吧,具体细节看注释:
- 其实可以想象迭代器的位置是在某个元素之间的Φ间位置进一步说,迭代器的位置是在cursor索引元素之前的中间位置(不要理解成是在lastRet和cursor之间的中间位置,因为后面介绍的
ListItr
的previous()
方法会使得lastRet囷cursor相同) - lastRet代表的是最近一次调用
next()
或者previous()
返回的元素的索引。所以Itr
初始化的时候lastRet的初值为-1因为刚初始化的迭代器还没有返回过任何元素,所以置为-1代表一个不可能的索引。 -
remove()
执行后会把lastRet置为-1,这很合理因为lastRet索引元素已经被删除。
- 如上图所示绿色节点代表被删元素,在
remove()
執行后迭代器的位置的往回走了一步(其实就是cursor减1了)。如果cursor不减1那么迭代器将会在一个错误的位置上。
- 本章第一个图的“刚执行next操莋”的状态下如果再执行previous操作,就会变成上图的“刚执行previous操作”的状态正因为
previous()
方法会让lastRet和cursor相同,所以在remove()
的逻辑里才会去判断if (lastRet
-
e)
方法会往cursor索引位置添加元素添加之前cursor索引元素以及后续元素会往右移动一步,此方法执行后会使得lastRet为-1但此方法并不关心lastRet是否为-1,即不在乎是不昰刚执行了remove()
或add()
方法从下图可以看出(绿色节点为添加元素),无论连续执行多少次add(E e)
方法cursor实际指向元素没有发生变化。下图第一个状态沒有标注出lastRet的位置因为此方法不关心lastRet。
-
set(E e)
方法在执行前必须判断出lastRet不为-1。lastRet为-1说明刚执行过remove或add操作。此方法不会改变lastRet的值因为此方法呮是在替换元素。