一、AbstractList的结构
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
......
protected transient int modCount = 0;
......
其继承AbstractCollection集合抽象类,同时实现关于List集合的List接口,这里的参数modCount表示List修改的次数。
二、AbstractList中关于迭代器实现的子类
下面我们来看下在AbstractList中关于Iterator接口的实现(能直接访问到AbstractList的成员变量的值)。
1、Itr
1)、成员变量
private class Itr implements Iterator<E> {
int cursor = 0;
int lastRet = -1;
int expectedModCount = modCount;
该子类有3个成员变量,其中:cursor表示下次获取元素的时候返回哪个位置的值、lastRet表示本次获取元素时返回的是哪个位置的值(如果该位置的元素被删除了,就重置其为-1),expectedModCount表示预期这个List被修改的次数。
2)、一些方法
public boolean hasNext() {
return cursor != size();
}
这个方法就是看cursor目前指的位置是否已经到了最后了。
public E next() {
checkForComodification();
try {
int i = cursor;
E next = get(i);
lastRet = i;
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
这个方法首先是判断预期修改的次数是否等于modCount修改的次数,如果不相等,可以存在并发操作这个List导致元素改变了,所以这里其是会抛一个ConcurrentModificationException的异常,如果判断满足,进行执行。就获取cursor位置的值返回,再将这个cursor(i)的值赋值给lastRet,然后cursor加一指向下次应该获取的index位置。
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
这个首先是判断lastRet,如果小于0表示这个位置的元素已经被移除了(迭代器遍历先是next,所以next会进行lastRet对应的设置)则抛出异常,再进行检查看是否有并发修改,之后我们可以看到其是直接调用的AbstractList的remove方法,再进行cursor的自减,将lastRet置为-1,将AbstractList的modCount同步给Itr的expectedModCount。
2、ListItr
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
cursor = index;
}
可以看到其继承了Itr同时实现了ListIterator接口,下面我们来看下其对ListIterator的方法实现
1)、关于ListIterator接口的方法实现
public boolean hasPrevious() {
return cursor != 0;
}
这个就是往前获取,看这个迭代器前面还没有没有元素。
public E previous() {
checkForComodification();
try {
int i = cursor - 1;
E previous = get(i);
lastRet = cursor = i;
return previous;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
可以看到这里与前面的next不同的是,next方法对cursor的增加是上一次操作的时候,而这里对cursor的减1是在本次。
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor-1;
}
这个方法就是获取下/上一次获取元素对应的index的值。
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.set(lastRet, e);
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
这个方法就是将新元素设置在lastRet位置。
public void add(E e) {
checkForComodification();
try {
int i = cursor;
AbstractList.this.add(i, e);
lastRet = -1;
cursor = i + 1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
这个方法与上面对应,是设置在cursor位置。
三、方法
1、add
public boolean add(E e) {
add(size(), e);
return true;
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
add方法是用于添加元素,可以看到其调用的是含有index的方法(添加到对应index的位置),然后有些AbstractList的子类可能会有限制可能不能添加null值,有些子类能添加,这个add(int index, E element)方法要子类去重写,现在是直接抛的不支持操作的异常。
2、remove
public E remove(int index) {
throw new UnsupportedOperationException();
}
3、indexOf
public int indexOf(Object o) {
ListIterator<E> it = listIterator();
if (o==null) {
while (it.hasNext())
if (it.next()==null)
return it.previousIndex();
} else {
while (it.hasNext())
if (o.equals(it.next()))
return it.previousIndex();
}
return -1;
}
public ListIterator<E> listIterator() {
return listIterator(0);
}
public ListIterator<E> listIterator(final int index) {
rangeCheckForAdd(index);
return new ListItr(index);
}
这个方法就是用来找到对应元素的index的位置值,其使用的迭代器实现是ListIterator,这里就是遍历判断(要明白这里it.next()再通过
it.previousIndex()返回对应的位置),没找到返回-1。
5、lastIndexOf
public int lastIndexOf(Object o) {
ListIterator<E> it = listIterator(size());
if (o==null) {
while (it.hasPrevious())
if (it.previous()==null)
return it.nextIndex();
} else {
while (it.hasPrevious())
if (o.equals(it.previous()))
return it.nextIndex();
}
return -1;
}
这个方法就是从后往前遍历,所以回去的是最后一个与o相等元素的位置,前面indexOf是获取第一个与入参相等元素的位置
6、clear
public void clear() {
removeRange(0, size());
}
protected void removeRange(int fromIndex, int toIndex) {
ListIterator<E> it = listIterator(fromIndex);
for (int i=0, n=toIndex-fromIndex; i<n; i++) {
it.next();
it.remove();
}
}
这个方法就是迭代器遍历清空List中的元素。
7、rangeCheckForAdd
private void rangeCheckForAdd(int index) {
if (index < 0 || index > size())
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size();
}
这个方法就是用来判断传入的index是不是超过了List的元素访问。
8、subList
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size());
return (this instanceof RandomAccess ?
new RandomAccessSubList<>(this, fromIndex, toIndex) :
new SubList<>(this, fromIndex, toIndex));
}
这个就是获取List的子集合,然后这里的RandomAccess只是用于例如遍历算法的选择,如果这个List本身有RandomAccess接口,就返回RandomAccessSubList,如果不是就返回SubList。
private static class RandomAccessSubList<E>
extends SubList<E> implements RandomAccess {
这个SubList就不展开了,这里要注意的是其等于是在原List上限制其的开始index及结束index,并没有出现copy一份新的子集合,所以如果对原List的元素修改是会对SubList中元素也改变,因为这两者是对同一对象的引用。