java.util.AbstractList源码解析

AbstractList

1. 介绍

AbstractList是对List的一个主要实现,如果要实现不可修改的list,程序需要去扩展这个类,实现getsize方法;如果要实现可修改的list,必须额外实现set方法,如果集合的大小也可以改变,还需要实现addremove方法。iteratorlist iterator已经在这个类实现好了。

AbstractCollection
AbstractList
List
ArrayList
Vector
AbstractSequentialList

2. add

public boolean add(E e) {
    add(size(), e);
    return true;
}

添加元素到集合的末尾

3. get

    public abstract E get(int index);

根据索引获取元素

4. set

public E set(int index, E element) {
    throw new UnsupportedOperationException();
}

在index位置设置元素element,覆盖原来的元素

5. add

public void add(int index, E element) {
    throw new UnsupportedOperationException();
}

在index添加元素element

6.remove

public E remove(int index) {
    throw new UnsupportedOperationException();
}

移除某个索引位置的元素

7. 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;
    }

从其实位置搜索元素o,如果当前集合不包含此元素,返回-1

8. 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的位置,初始化ListIterator时,加入游标位置为末尾。

9. clear

    public void clear() {
        removeRange(0, size());
    }

清空所有元素

10. addAll

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

在索引位置加入集合c

11. iterator

    public Iterator<E> iterator() {
        return new Itr();
    }

返回当前集合的迭代器,下面看一下迭代器的实现

private class Itr implements Iterator<E> {

    int cursor = 0;

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

Iterator是单项向下循环

cursor: 游标的位置

lastRet: 最后一次调用next或者previous(在ListIterator中)的位置,如果调用了remove,会置为-1

expectedModCount: 修改次数,用来监测是否有并发修改

hasNext(): 是否到达集合末尾,用来判断是否还有下一个元素

next(): 返回当前游标cursor的元素,并把lastRet置为当前元素的游标位置,然后游标+1。在调用next前一定要先调用hasNext否则可能出现越界

remove():移除lastRet所指向的元素,如果为-1时,会抛出异常。如果移除的元素在游标前面,则游标-1,然后lastRet置为-1,重新赋值修改次数expectedModCount

checkForComodification(): 如果在操作过程中,集合结构发生变化,会抛出ConcurrentModificationException异常

12. listIterator

    public ListIterator<E> listIterator() {
        return listIterator(0);
    }

    public ListIterator<E> listIterator(final int index) {
        rangeCheckForAdd(index);

        return new ListItr(index);
    }

返回list迭代器,index为游标的位置,下面看看ListIterator的实现

private class ListItr extends Itr implements ListIterator<E> {
    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();
        }
    }
}

ListItr继承了Itr实现了ListIterator,游标可以向前向后移动。Itr中向后移动与删除功能已经实现了,这里主要实现了游标向前移动的操作。 在ListIterator中说明,游标是介于next与previous元素之间的,但这里的实现用了一个技巧,游标其实指向了next的位置,游标-1为previous的元素,因为在Itr实现中,每一次调用next先获取当前游标的元素,然后游标+1,相当于上一个元素位置就是当前游标-1。

ListItr(int index): 构造方法,设置游标的位置

hasPrevious:判断是否有上一个元素,如果当前游标位置为0,就没有上一个元素

previous:返回上一个元素(当前游标-1位置的元素),然后重新赋值cursor与lastRet的值

nextIndex: 返回下一个元素游标的位置

previousIndex:返回上一个游标的位置

set: 在lastRet上设置值,然后重新给expectedModCount赋值

add: 在当前游标位置添加元素,然后lastRet置为-1,游标+1,重新给expectedModCount赋值,添加元素以后不会影响next返回的值,但是调用previous会返回当前添加的元素

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

比较两个集合是否相等

  • 先判断是否是当前对象
  • 类型是否一样
  • 挨个元素比较
  • 最后一步可以看成长度是否一样

14. hashCode

    public int hashCode() {
        int hashCode = 1;
        for (E e : this)
            hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
        return hashCode;
    }

计算hashCode,因子是31和String的一样

15. removeRange

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

移除范围,左闭右开区间

16. modCount

    protected transient int modCount = 0;

标志修改次数

17.RandomAccessSpliterator

static final class RandomAccessSpliterator<E> implements Spliterator<E> {

    private final List<E> list;
    private int index; // current index, modified on advance/split
    private int fence; // -1 until used; then one past last index

    // The following fields are valid if covering an AbstractList
    private final AbstractList<E> alist;
    private int expectedModCount; // initialized when fence set

    RandomAccessSpliterator(List<E> list) {
        assert list instanceof RandomAccess;

        this.list = list;
        this.index = 0;
        this.fence = -1;

        this.alist = list instanceof AbstractList ? (AbstractList<E>) list : null;
        this.expectedModCount = alist != null ? alist.modCount : 0;
    }

    /** Create new spliterator covering the given  range */
    private RandomAccessSpliterator(RandomAccessSpliterator<E> parent,
                            int origin, int fence) {
        this.list = parent.list;
        this.index = origin;
        this.fence = fence;

        this.alist = parent.alist;
        this.expectedModCount = parent.expectedModCount;
    }

    private int getFence() { // initialize fence to size on first use
        int hi;
        List<E> lst = list;
        if ((hi = fence) < 0) {
            if (alist != null) {
                expectedModCount = alist.modCount;
            }
            hi = fence = lst.size();
        }
        return hi;
    }

    public Spliterator<E> trySplit() {
        int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
        return (lo >= mid) ? null : // divide range in half unless too small
                new RandomAccessSpliterator<>(this, lo, index = mid);
    }

    public boolean tryAdvance(Consumer<? super E> action) {
        if (action == null)
            throw new NullPointerException();
        int hi = getFence(), i = index;
        if (i < hi) {
            index = i + 1;
            action.accept(get(list, i));
            checkAbstractListModCount(alist, expectedModCount);
            return true;
        }
        return false;
    }

    public void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        List<E> lst = list;
        int hi = getFence();
        int i = index;
        index = hi;
        for (; i < hi; i++) {
            action.accept(get(lst, i));
        }
        checkAbstractListModCount(alist, expectedModCount);
    }

    public long estimateSize() {
        return (long) (getFence() - index);
    }

    public int characteristics() {
        return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
    }

    private static <E> E get(List<E> list, int i) {
        try {
            return list.get(i);
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    static void checkAbstractListModCount(AbstractList<?> alist, int expectedModCount) {
        if (alist != null && alist.modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }
}

随机访问的可分割迭代器,具体可看Spliterator

18. SubList

private static class SubList<E> extends AbstractList<E> {
    private final AbstractList<E> root;
    private final SubList<E> parent;
    private final int offset;
    protected int size;

    /**
     * Constructs a sublist of an arbitrary AbstractList, which is
     * not a SubList itself.
     */
    public SubList(AbstractList<E> root, int fromIndex, int toIndex) {
        this.root = root;
        this.parent = null;
        this.offset = fromIndex;
        this.size = toIndex - fromIndex;
        this.modCount = root.modCount;
    }

    /**
     * Constructs a sublist of another SubList.
     */
    protected SubList(SubList<E> parent, int fromIndex, int toIndex) {
        this.root = parent.root;
        this.parent = parent;
        this.offset = parent.offset + fromIndex;
        this.size = toIndex - fromIndex;
        this.modCount = root.modCount;
    }

    public E set(int index, E element) {
        Objects.checkIndex(index, size);
        checkForComodification();
        return root.set(offset + index, element);
    }

    public E get(int index) {
        Objects.checkIndex(index, size);
        checkForComodification();
        return root.get(offset + index);
    }

    public int size() {
        checkForComodification();
        return size;
    }

    public void add(int index, E element) {
        rangeCheckForAdd(index);
        checkForComodification();
        root.add(offset + index, element);
        updateSizeAndModCount(1);
    }

    public E remove(int index) {
        Objects.checkIndex(index, size);
        checkForComodification();
        E result = root.remove(offset + index);
        updateSizeAndModCount(-1);
        return result;
    }

    protected void removeRange(int fromIndex, int toIndex) {
        checkForComodification();
        root.removeRange(offset + fromIndex, offset + toIndex);
        updateSizeAndModCount(fromIndex - toIndex);
    }

    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();
        root.addAll(offset + index, c);
        updateSizeAndModCount(cSize);
        return true;
    }

    public Iterator<E> iterator() {
        return listIterator();
    }

    public ListIterator<E> listIterator(int index) {
        checkForComodification();
        rangeCheckForAdd(index);

        return new ListIterator<E>() {
            private final ListIterator<E> i =
                    root.listIterator(offset + index);

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

            public void set(E e) {
                i.set(e);
            }

            public void add(E e) {
                i.add(e);
                updateSizeAndModCount(1);
            }
        };
    }

    public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);
        return new SubList<>(this, fromIndex, toIndex);
    }

    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 (root.modCount != this.modCount)
            throw new ConcurrentModificationException();
    }

    private void updateSizeAndModCount(int sizeChange) {
        SubList<E> slist = this;
        do {
            slist.size += sizeChange;
            slist.modCount = root.modCount;
            slist = slist.parent;
        } while (slist != null);
    }
}

截取集合,实际根本就没有返回新集合,还是原来的集合,根据构造函数fromIndex,toIndex设置了偏移量offset=fromIndex,和size=toIndex-fromIndex。每次还是操作的原集合,只不过加了一个偏移量offset。

19. RandomAccessSubList

private static class RandomAccessSubList<E>
        extends SubList<E> implements RandomAccess {

    /**
     * Constructs a sublist of an arbitrary AbstractList, which is
     * not a RandomAccessSubList itself.
     */
    RandomAccessSubList(AbstractList<E> root,
            int fromIndex, int toIndex) {
        super(root, fromIndex, toIndex);
    }

    /**
     * Constructs a sublist of another RandomAccessSubList.
     */
    RandomAccessSubList(RandomAccessSubList<E> parent,
            int fromIndex, int toIndex) {
        super(parent, fromIndex, toIndex);
    }

    public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);
        return new RandomAccessSubList<>(this, fromIndex, toIndex);
    }
}

随机访问截取集合,实际就是用的SubList

20. 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));
    }
    static void subListRangeCheck(int fromIndex, int toIndex, int size) {
        if (fromIndex < 0)
            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
        if (toIndex > size)
            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
        if (fromIndex > toIndex)
            throw new IllegalArgumentException("fromIndex(" + fromIndex +
                                               ") > toIndex(" + toIndex + ")");
    }

截取集合,根据18/19两个内部类,判断是否有随机访问标志,调用不同的实现

实时内容请关注微信公众号,公众号与博客同时更新:程序员星星
实时内容请关注微信公众号,公众号与博客同时更新

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值