jdk源码阅读之AbstractList

来源:互联网 发布:天龙八部装备精通数据 编辑:程序博客网 时间:2024/05/17 22:42

AbstractList继承了AbstractCollection, 实现了List接口。它提供了实现“随机访问”的List的一些方法。可以最大限度的减少实现随机访问的数据存储(如LinkList)的工作量,而如果需要实现随机访问的List(如ArrayList)则最好使用AbstractList。

AbstractList在Java Collection Framework中的位置如下图示,jdk中默认实现为ArrayList。

这里写图片描述

如果需要实现不可变List,则继承类必需实现get(int)size()两个方法。可变list则必需覆盖set(int, E)add(int,E)remove(int)等方法。

根据Collection接口规范,实现类也需要有一个无参的constructor。

默认必须要实现类覆盖的方法

包括add()remove()set()addAll()

public boolean add(E e) {    add(size(), e);    return true;}
public void add(int index, E element) {    throw new UnsupportedOperationException();}
public E set(int index, E element) {    throw new UnsupportedOperationException();}
public E remove(int index) {    throw new UnsupportedOperationException();}
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;}

其中rangeCheckForAdd(index)用来检查Index是否超出则抛出IndexOutOfBoundsException。由于这里的add()抛出UnsupportedOperationException异常,所以实现类如果需要使用该方法,就必须复写add()方法。此外,很多实现类复写该方法以提高执行效率。

已经实现的方法

包括indexOf()lastIndexOf()clear():

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 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为空,但该List不允许空元素时,上述两操作会抛出NullPointerException。

 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();    }}

实现的迭代器接口

public Iterator<E> iterator() {    return new Itr();}
public ListIterator<E> listIterator() {    return listIterator(0);}
public ListIterator<E> listIterator(final int index) {    rangeCheckForAdd(index);    return new ListItr(index);}

内置迭代器

AbstractList 内部已经提供了 Iterator, ListIterator 迭代器的实现类,分别为 Itr, ListItr, 不需要实现类重新提供。

Iterator迭代器

源码如下:

private class Itr implements Iterator<E> {    //游标,下一次调用(迭代器)时返回元素的索引。    int cursor = 0;    //上一次调用时的元素的索引。如果调用remove()方法,则该值回复重设成-1    int lastRet = -1;    //用来判断是否发生并发操作的标示,如果这两个值不一致,就会报错    int expectedModCount = modCount;    public boolean hasNext() {       return cursor != size();    }    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();        }    }    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();        }    }    //时刻检查是否有并发修改操作    final void checkForComodification() {        if (modCount != expectedModCount)            throw new ConcurrentModificationException();    }}

可以看到 Itr 只是简单实现了 Iterator 的 next, remove 方法。

ListIterator

//ListItr是Itr的增强版,在Itr基础上多了向前和set操作。private class ListItr extends Itr implements ListIterator<E> {    ListItr(int index) {        super();        cursor = index;    }    public boolean hasPrevious() {        return cursor != 0;    }    public int nextIndex() {        return cursor;    }    public int previousIndex() {        return cursor - 1;    }    @SuppressWarnings("unchecked")    public E previous() {        checkForComodification();        //获取游标前面一位元素        int i = cursor - 1;        if (i < 0)            throw new NoSuchElementException();        Object[] elementData = ArrayList.this.elementData;        if (i >= elementData.length)            throw new ConcurrentModificationException();        cursor = i;        return (E) elementData[lastRet = i];    }    public void set(E e) {        if (lastRet < 0)            throw new IllegalStateException();        checkForComodification();        try {            ArrayList.this.set(lastRet, e);        } catch (IndexOutOfBoundsException ex) {            throw new ConcurrentModificationException();        }    }    public void add(E e) {        checkForComodification();        try {            int i = cursor;            ArrayList.this.add(i, e);            cursor = i + 1;            lastRet = -1;            expectedModCount = modCount;        } catch (IndexOutOfBoundsException ex) {            throw new ConcurrentModificationException();        }    }}

SubList与RandomAccessSubList

用来返回指定索引(fromIndex和toIndex, 前闭后开)之间的部分视图。如果fromIndex和toIndex相等,返回长度为0的list。返回的List是原来List中的一部分的视图的引用。任何对返回的subList的修改都将同步到原List中,反之亦然。
SubList继承了AbstractList。
RandomAccessSubList用来标示可以“随机访问”的实现的子List。它实现了RandomAccess接口,继承了SubList。RandomAccess接口用来标示一个类是否可以随机按索引访问。比如遍历,实现了 RandomAccess 的集合使用 get():

for (int i=0, n=list.size(); i &lt; n; i++)    list.get(i);

AbstractList的subList()方法如下:

    public List<E> subList(int fromIndex, int toIndex) {        return (this instanceof RandomAccess ?                new RandomAccessSubList<>(this, fromIndex, toIndex) :                new SubList<>(this, fromIndex, toIndex));    }

SubList的源码

class SubList<E> extends AbstractList<E> {    private final AbstractList<E> l;    private final int offset;    private int size;    //构造参数:    //list :父 List    //fromIndex : 从父 List 中开始的位置    //toIndex : 在父 List 中哪里结束    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;        //和父类使用同一个 modCount        this.modCount = l.modCount;    }    //使用父类的 set()    public E set(int index, E element) {        rangeCheck(index);        checkForComodification();        return l.set(index+offset, element);    }    //使用父类的 get()    public E get(int index) {        rangeCheck(index);        checkForComodification();        return l.get(index+offset);    }    public int size() {        checkForComodification();        return size;    }    //根据子 List 开始的位置,加上偏移量,直接在父List 上进行添加    public void add(int index, E element) {        rangeCheckForAdd(index);        checkForComodification();        l.add(index+offset, element);        this.modCount = l.modCount;        size++;    }    //根据子 List 开始的位置,加上偏移量,直接在父 List 上进行删除    public E remove(int index) {        rangeCheck(index);        checkForComodification();        E result = l.remove(index+offset);        this.modCount = l.modCount;        size--;        return result;    }    //调用父类的 局部删除    protected void removeRange(int fromIndex, int toIndex) {        checkForComodification();        l.removeRange(fromIndex+offset, toIndex+offset);        this.modCount = l.modCount;        size -= (toIndex-fromIndex);    }    public boolean addAll(Collection<? extends E> c) {        return addAll(size, c);    }    //还是使用的父类 addAll()    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();    }    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++;            }        };    }    public List<E> subList(int fromIndex, int toIndex) {        return new SubList<>(this, fromIndex, toIndex);    }    private void rangeCheck(int index) {        if (index < 0 || index >= size)            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));    }    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;    }    private void checkForComodification() {        if (this.modCount != l.modCount)            throw new ConcurrentModificationException();    }}

所以SubList虽然自立门户,等到要干活时,使用的都是父类的方法,父类的数据。所以可以通过它来间接操作父 List。

原创粉丝点击