这次来看一下AbstractList,也就是ArrayList他亲爹。AbstractList存在的意义和AbstractCollection差不多,意义在于简化List的实现复杂度。如果你想实现List,你只需要继承一下AbstratList,然后实现一下get()和zise()。好了,你的List实现了。
咱们先看看AbstractList是怎么定义的
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>
特点:1抽象类
2 继承自AbstractCollection
3 实现了List
接下来,我们来了解AbstractList都实现了哪些功能
构造函数
protected AbstractList() {
}
很遗憾,AbstractList也不支持添加操作,想要支持add操作,子类只能重写add方法。
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public boolean add(E e) {
add(size(), e);
return true;
}
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
boolean modified = false;
for (E e : c) {
add(index++, e);
modified = true;
}
return modified;
}
关键set操作也不支持。。。
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
你以为这就结束了,图样图森破。get()也需要自己实现
abstract public E get(int index);
哈哈哈,删除也不支持,惊不惊喜,意不意外?
public E remove(int index) {
throw new UnsupportedOperationException();
}
接下来这个方法就很有用了,返回某个元素在List中的位置,我们来看一下代码
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;
}
但是有一个ListIterator对象就很烦人了,我们在之前的博客中介绍过这个接口,那么接下来,我们来看一下实现类
private class Itr implements Iterator<E>
必须说明的是,这个类是AbstractList的内部类,所以只能在AbstractList内部使用,因此我们平时只需要知道有这么回事,没必要刻意研究(但是我们不就是在研究源码嘛,哈哈哈)。Itr实现了Iterotor接口,是AbstractList的迭代器对象。
接下来看一下这个内部类的属性
int cursor = 0;
调用next方法返回的元素的下标,默认为0;
int lastRet = -1;
代表最近一次调用next或者pervious方法返回元素的下标。如果元素被删除,则重置为-1;
int expectedModCount = modCount;
迭代器对象认为当前列表应该具有的modValue值,如果违背了这个期望,那么迭代器也会检测到,并且并发修改;
public boolean hasNext() {
return cursor != size();
}
判断迭代器是否还有下一个元素;
如果next()方法返回的元素的下标不是List的元素数量,说明有下个元素。
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
这个方法是为了检查modCount的值,如果和expectedModCount的值不一样,说明出现了并发异常,所以会直接抛出异常。
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();
}
}
首先记录当前元素(或者叫下一个元素)的下标,然后根据下标拿到元素;重置lastRet和cursor
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();
}
}
当modCount和expectedModCount值不一样时,说明出现了并发量过高,导致出现了异步修改。需要抛出异常
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
接下来是另一个迭代器,根据我的理解,这个迭代器返回的是当前元素的迭代器对象。
private class ListItr extends Itr implements ListIterator<E>
实现了ListIterator,集成于Itr
构造函数
ListItr(int index) {
cursor = index;
}
判断是否有上一个元素
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();
}
}
获取下一个元素的下标
public int nextIndex() {
return cursor;
}
获取上一个元素的下标
public int previousIndex() {
return cursor-1;
}
元素替换
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();
}
}
增加一个元素
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();
}
}
接下来看看另一个内部类
class SubList<E> extends AbstractList<E>
顾名思义,是一个List的儿子,或者说,是为了截取List的
先看看他的成员变量
private final AbstractList<E> l;
private final int offset;
private int size;
也不写注释。。算了,直接看构造函数
SubList(AbstractList<E> list, int fromIndex, int toIndex) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > list.size())
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
l = list;
offset = fromIndex;
size = toIndex - fromIndex;
this.modCount = l.modCount;
}
三个参数,我大胆的猜测一下他们的含义。
list:需要截取的List。fromIndex:从哪里开始截取。toIndex:截取到哪里。
将需要截取的list赋值给l,offset的值为fromIndex。截取后的list的size为toIndex-fromIndex
检查某个下标是否合法
private void rangeCheck(int index) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
如果传入的下标为0或者大于size,说明这个size就不合法
监控是否出现了并发修改
private void checkForComodification() {
if (this.modCount != l.modCount)
throw new ConcurrentModificationException();
}
元素替换
public E set(int index, E element) {
rangeCheck(index);
checkForComodification();
return l.set(index+offset, element);
}
根据下标获取元素
public E get(int index) {
rangeCheck(index);
checkForComodification();
return l.get(index+offset);
}
获取截取后的List长度
public int size() {
checkForComodification();
return size;
}
添加元素
public void add(int index, E element) {
rangeCheckForAdd(index);
checkForComodification();
l.add(index+offset, element);
this.modCount = l.modCount;
size++;
}
移除元素
public E remove(int index) {
rangeCheck(index);
checkForComodification();
E result = l.remove(index+offset);
this.modCount = l.modCount;
size--;
return result;
}
添加一个集合
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
添加一个集合中的一部分
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
int cSize = c.size();
if (cSize==0)
return false;
checkForComodification();
l.addAll(offset+index, c);
this.modCount = l.modCount;
size += cSize;
return true;
}
获取迭代器对象
public Iterator<E> iterator() {
return listIterator();
}
获取ListIterator对象
public ListIterator<E> listIterator(final int index) {
checkForComodification();
rangeCheckForAdd(index);
return new ListIterator<E>() {
private final ListIterator<E> i = l.listIterator(index+offset);
public boolean hasNext() {
return nextIndex() < size;
}
public E next() {
if (hasNext())
return i.next();
else
throw new NoSuchElementException();
}
public boolean hasPrevious() {
return previousIndex() >= 0;
}
public E previous() {
if (hasPrevious())
return i.previous();
else
throw new NoSuchElementException();
}
public int nextIndex() {
return i.nextIndex() - offset;
}
public int previousIndex() {
return i.previousIndex() - offset;
}
public void remove() {
i.remove();
SubList.this.modCount = l.modCount;
size--;
}
public void set(E e) {
i.set(e);
}
public void add(E e) {
i.add(e);
SubList.this.modCount = l.modCount;
size++;
}
};
}
截取List
public List<E> subList(int fromIndex, int toIndex) {
return new SubList<>(this, fromIndex, toIndex);
}
接下来看看最后一个内部类
class RandomAccessSubList<E> extends SubList<E> implements RandomAccess
继承自SubList,实现了RandomAccess
构造函数
RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) {
super(list, fromIndex, toIndex);
}
List截取
public List<E> subList(int fromIndex, int toIndex) {
return new RandomAccessSubList<>(this, fromIndex, toIndex);
}
这时候,我们再来看一下indexOf这个方法的含义。先获取一个ListIterator对象,随后判断是否为空,其实也就是使用迭代器遍历,使用equals来判断集合中是否有这个元素。可是我们注意到他的最后返回值调用的是ListIterator对象的previousIndex()方法,我们回想一下这个方法是怎么实现的呢?返回值是cursor-1。那我们在想一下,cursor的含义是什么?简单来说,就是下一次要调用next()方法的元素的下标。
假设我们现在有一个动物List,里面有一只猫,一只狗,一只狮子,顺序就是猫,狗,狮子。现在我想知道狮子的位置,先创建ListIterator,然后判断狮子是否为空?不是,然后调用ListIterator的hasNext方法。
第一次循环,cursor为0,size()为3,hasNext返回值为true。然后调用next(),得到的元素是猫,继续循环
第二次循环,cursor为1,size()为3,hasNext返回值为true,继续调用next(),得到的元素是狗,继续循环
第三次循环,cursor为2,size()为3,hasNext返回值为true,继续调用next(),得到的元素是狮子,符合条件,调用previousIndex()方法,但是我们要注意,此时cursor的值为3,那么,previousIndex()的返回值就是2,即狮子的下标为2
接下来的方法和indexOf差不多,只不过是获取list内某个元素最后的位置。我们知道list的元素是可以重复的,比如,我的list里面的元素为金、木、水、火、土、金、水、火。我现在想知道火最后一次出现的位置,那么就得调用这个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;
}
具体实现也很有意思,首先,ListIterator的构造方法就采用了有参构造函数,我们顺一下方法的执行过程。参数为火
1 执行构造函数,获取ListIterator对象,此时,size()为8,cursor为8
2 判断是否为空,当然不是空。。。
3 执行hasPrevious(),结果为true
4 执行previous(),lastRet的值为7,cursor也为7,返回值为火,
5 equals对比后结果正确,执行nextIndex()
6 返回值为7.证明火最后一次出现的位置为7
接下来是清空list
public void clear() {
removeRange(0, size());
}
这样的话,继续研究一下removeRnage这个方法
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();
}
}
继续顺一下,此时假设集合为:金、木、水、火、土
那么,fromIndex为0,toIndex为5
获取ListIterator对象,cursor为0。n为5。循环开始
第一次循环,i=0,n=5,执行next()。cursor为1,lastRet为0。然后执行remove()。检查是否出现并发修改,然后移除下标为0(lastRet)的元素。此时,lastRet小于cursor,cursor执行自减操作,cursor为0。lastRet重置为-1.
list内的元素:木、水、火、土
第二次循环,i=1,n=5,执行next()。cursor为1,lastRet为0。然后执行remove()。检查是否出现并发修改,然后移除下标为0(lastRet)的元素。此时,lastRet小于cursor,cursor执行自减操作,cursor为0。lastRet重置为-1.
list内的元素:水、火、土
第三次循环,i=2,n=5,执行next()。cursor为1,lastRet为0。然后执行remove()。检查是否出现并发修改,然后移除下标为0(lastRet)的元素。此时,lastRet小于cursor,cursor执行自减操作,cursor为0。lastRet重置为-1.
list内的元素:火、土
第四次循环,i=3,n=5,执行next()。cursor为1,lastRet为0。然后执行remove()。检查是否出现并发修改,然后移除下标为0(lastRet)的元素。此时,lastRet小于cursor,cursor执行自减操作,cursor为0。lastRet重置为-1.
list内的元素:土
第五次循环,i=4,n=5,执行next()。cursor为1,lastRet为0。然后执行remove()。检查是否出现并发修改,然后移除下标为0(lastRet)的元素。此时,lastRet小于cursor,cursor执行自减操作,cursor为0。lastRet重置为-1.
list内的元素:
元素清空完毕
获取迭代器对象
public Iterator<E> iterator() {
return new Itr();
}
获取ListIterator对象,无参
public ListIterator<E> listIterator() {
return listIterator(0);
}
有参
public ListIterator<E> listIterator(final int index) {
rangeCheckForAdd(index);
return new ListItr(index);
}
截取list
public List<E> subList(int fromIndex, int toIndex) {
return (this instanceof RandomAccess ?
new RandomAccessSubList<>(this, fromIndex, toIndex) :
new SubList<>(this, fromIndex, toIndex));
}
equals比较
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof List))
return false;
ListIterator<E> e1 = listIterator();
ListIterator<?> e2 = ((List<?>) o).listIterator();
while (e1.hasNext() && e2.hasNext()) {
E o1 = e1.next();
Object o2 = e2.next();
if (!(o1==null ? o2==null : o1.equals(o2)))
return false;
}
return !(e1.hasNext() || e2.hasNext());
}
就是把当前集合和对比的对象分别遍历,每次都用来对比,所有都一样的话,证明两个集合完全相同。
至此,AbstractList的源码分析完毕