JDK源码阅读——集合框架——AbstractList

 

这次来看一下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的源码分析完毕

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值