Java 集合深入理解 :AbstractList类

Posted 踩踩踩从踩

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 集合深入理解 :AbstractList类相关的知识,希望对你有一定的参考价值。

前言
AbstractList 此类提供 List 接口的骨干实现,从而最大限度地减少了实现由“随机访问”数据存储(如数组)支持的接口所需的工作。对于连续的访问数据(如链表),应优先使用AbstractSequentialList,而非此类, 可以了解该类也是很有必要的

全篇注释

/**
*此类提供了{@link List}的框架实现接口以最小化实现此接口所需的工作
*由“随机访问”数据存储(如数组)支持。对于顺序访问数据(如链表),{@link AbstractSequentialList}应该优先于这个类使用。<p>要实现一个不可修改的列表,程序员只需扩展这个类并为{@link#get(int)}和{@link List#size()size()}方法。
*<p>要实现可修改列表,程序员必须另外重写{@link#set(int,Object)set(int,E)}方法(否则抛出一个{@code UnsupportedOperationException})。如果列表是
*可变大小程序员还必须重写{@link#add(int,Object)add(int,E)}和{@link#remove(int)}方法。
*<p>程序员通常应该提供void(无参数)和collection构造函数,按照{@link Collection}接口中的建议规范。
*<p>与其他抽象集合实现不同,程序员是这样做的<i>不</i>必须提供迭代器实现;迭代器和
*列表迭代器是由这个类在“随机访问”之上实现的方法:
*{@link#get(int)},
*{@link#set(int,Object)set(int,E)},
*{@link#add(int,Object)add(int,E)}和
*{@link#remove(int)}。
*<p>此类中每个非抽象方法的文档描述了其具体实施。如果正在实现的集合允许更高效的实现。
* <p>This class is a member of the
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
 * Java Collections Framework</a>.
 *
 * @author  Josh Bloch
 * @author  Neal Gafter
 * @since 1.2
 */

注释解析
1.框架实现接口以最小化实现此接口所需基本方法
2.由“随机访问”数据存储(如数组)支持
3.要实现一个不可修改的列表,程序员只需扩展这个类并为{@link#get(int)}和{@link List#size()size()}方法
4.要实现可修改列表,程序员必须另外重写 set(int,Object)set(int,E)
6.对于链表AbstractSequentialList应该优先于这个类使用;
7.如果add remove等方法 没有实现,则会抛出UnsupportedOperationException 异常的
这个和AbstractCollection 中的注释描述的很像,都利用的模板方法,保证一些基础方法的实现,然后如果要实现可修改的点,需要实现对应的方法

Java 集合深入理解 (八) :Collection接口和list接口深入理解

add 方法

抽象类是没有实现add方法的,如果继承者没有实现add(int index, E element)则会抛出UnsupportedOperationException异常

  /**
   *将指定的元素追加到此列表的末尾(可选)操作)。<p>支持此操作的列表可能会限制可以将元素添加到此列表中。特别是一些
   *列表将拒绝添加空元素,其他列表将强制对可能添加的元素类型的限制。列表类应该在其文档中明确指定任何限制可以添加哪些元素。
     *
     * <p>This implementation calls {@code add(size(), e)}.
     *
     * <p>注意,这个实现抛出一个
     * {@code UnsupportedOperationException} unless
     * {@link #add(int, Object) add(int, E)} 被覆盖.
     *
     * @param 要附加到此列表的元素
     * @return {@code true} (as specified by {@link Collection#add})
     * @throws UnsupportedOperationException if the {@code add} 操作 表示此列表不支持
     *        
     * @throws ClassCastException  如果指定元素的类
     *         阻止将其添加到此列表
     * @throws NullPointerException 如果指定的元素为null
     *         列表不允许空元素
     * @throws IllegalArgumentException 如果这个元素的某些属性
     *         阻止将其添加到此列表
     */
    public boolean add(E e) {
        add(size(), e);
        return true;
    }
 /**
     * {@inheritDoc}
     *
     * <p>这个实现总是抛出一个
     * {@code UnsupportedOperationException}.
     *
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws ClassCastException            {@inheritDoc}
     * @throws NullPointerException          {@inheritDoc}
     * @throws IllegalArgumentException      {@inheritDoc}
     * @throws IndexOutOfBoundsException     {@inheritDoc}
     */
    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }
/**
     * {@inheritDoc}
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    abstract public E get(int index);
 /**
     * {@inheritDoc}
     *
     * <p>This implementation always throws an
     * {@code UnsupportedOperationException}.
     *
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws ClassCastException            {@inheritDoc}
     * @throws NullPointerException          {@inheritDoc}
     * @throws IllegalArgumentException      {@inheritDoc}
     * @throws IndexOutOfBoundsException     {@inheritDoc}
     */
    public E set(int index, E element) {
        throw new UnsupportedOperationException();
    }

 /**
     * {@inheritDoc}
     *
     * <p>This implementation always throws an
     * {@code UnsupportedOperationException}.
     *
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws ClassCastException            {@inheritDoc}
     * @throws NullPointerException          {@inheritDoc}
     * @throws IllegalArgumentException      {@inheritDoc}
     * @throws IndexOutOfBoundsException     {@inheritDoc}
     */
    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }

    /**
     * {@inheritDoc}
     *
     * <p>This implementation always throws an
     * {@code UnsupportedOperationException}.
     *
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws IndexOutOfBoundsException     {@inheritDoc}
     */
    public E remove(int index) {
        throw new UnsupportedOperationException();
    }

**抽象方法 **
继承者去实现 get(int index) set(int index, E element) remove(int index)
要不然在调用此方法时会抛出UnsupportedOperationException 异常

indexOf和lastIndexOf方法

抽象类提供了查找对象的方式
获取迭代器
一个从头开始寻找,一个从尾开始往前寻找,直到找到元素为止,包括调用的nextIndex 等方法,都是最后调用到get() 方法。

  /**
     * {@inheritDoc}
     *
     * <p>这个实现首先得到一个列表迭代器 (with
     * {@code listIterator()}).  然后,它在列表上迭代,直到找到指定的元素或到达列表的末尾。
     *
     * @throws ClassCastException   {@inheritDoc}
     * @throws NullPointerException {@inheritDoc}
     */
    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;
    }

    /**
     * {@inheritDoc}
     *
     * <p>这个实现首先得到一个指向末尾的列表迭代器
     * 名单上的 (with {@code listIterator(size())}).  然后,它迭代
     * 向后遍历列表,直到找到指定的元素,或者
     * 到达列表的开头。
     *
     * @throws ClassCastException   {@inheritDoc}
     * @throws NullPointerException {@inheritDoc}
     */
    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;
    }

批量操作

clear()方法
调用的removeRange方法
removeRange方法
通过将任何后续元素向左移动(减少其索引),元素来缩短列表,操作调用及其子列表。重写此方法以利用列表实现的内部可以改进此列表上,性能及其子列表。
fromIndex 是包含了的,toIndex是不包含,for (int i=0, n=toIndex-fromIndex; i<n; i++) {
这个关键点在这里,toIndex=fromIndex 该循环也是会进去一次的,所以fromIndex 也是会被删除的。 这在比如说arraylist中就被覆盖了,重写的,也是提高效率

 /**
     * 从此列表中删除所有元素(可选操作)。
     * 此呼叫返回后,列表将为空。
     *
     * <p>This implementation calls {@code removeRange(0, size())}.
     *
     * <p>注意这个实现抛出
     * {@code UnsupportedOperationException} unless {@code remove(int
     * index)} or {@code removeRange(int fromIndex, int toIndex)} is
     * overridden.
     *
     * @throws UnsupportedOperationException if the {@code clear} operation
     *         is not supported by this list
     */
    public void clear() {
        removeRange(0, size());
    }

  /**
    *从此列表中删除索引介于{@code fromIndex}(包含)和{@code toIndex}(独占)。将任何后续元素向左移动(减少其索引)。
    *这个调用通过{@code(toIndex-fromlindex)}元素来缩短列表。(如果{@code toIndex==fromIndex},则此操作无效。)
    *<p>此方法由此列表上的{@code clear}操作调用及其子列表。重写此方法以利用列表实现的内部可以改进此列表上{@code clear}
     操作的	性能及其子列表。
	*<p>此实现在{@codefromindex},并重复调用{@codelistiterator.next}
	*后跟{@code ListIterator.remove},直到完成整个范围
	*已删除<b> 注意:如果{@codelistiterator.remove}需要线性
	*时间,这个实现需要二次时间</b>
 	* @param fromIndex index of first element to be removed
     * @param toIndex index after last element to be removed
     */
    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();
        }
    }

addAll 方法
addAll 这个公共的方法,通过调用抽象的 add(index++, e);去实现,确实效率会慢很多,所以像arraylist这些实现类,就重写该方法

 /**
     * {@inheritDoc}
     *
     * <p>此实现获取指定集合上的迭代器并对其进行迭代,插入从 在适当的位置迭代这个列表,一次一个,
     * using {@code add(int, E)}.
     * 为了提高效率,许多实现将覆盖此方法。
     *
     * <p>Note that this implementation throws an
     * {@code UnsupportedOperationException} unless
     * {@link #add(int, Object) add(int, E)} is overridden.
     *
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws ClassCastException            {@inheritDoc}
     * @throws NullPointerException          {@inheritDoc}
     * @throws IllegalArgumentException      {@inheritDoc}
     * @throws IndexOutOfBoundsException     {@inheritDoc}
     */
    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;
    }

迭代器

这其中有两个迭代器通过iterator 和listIterator 方法给我们使用
1.Itr 迭代器
1.属性
cursor 后续调用下一个要返回的元素的索引。
lastRet 最近对下一个或的调用返回的元素的索引上一个。如果此元素被调用删除,则重置为-1移除。
也就是记录上个元素的索引,这在next方法中就能对比,如果remove了的话,就重置为-1;
2.next 和 remove方法
并在remove等操作中添加对lastRet 的判断, 防止多次删除等操作

2.ListItr
该迭代器 解释是实现依赖于备份列表,
从源码来说,相当于 Itr的增强,
set 方法,对节点的替换,
previous方法,后置遍历的方法
add 方法, 添加数据到末尾

Java 集合深入理解 (三) :java.util 包的集合中 fail-fast 快速失败机制

 /**
    *按正确的顺序返回此列表中元素的迭代器。<p>此实现返回迭代器接口,依赖于支持列表的{@code size()},
     *{@code get(int)}和{@code remove(int)}方法。
    *<p>请注意,此方法返回的迭代器将抛出{@link UnsupportedOperationException}响应其
    *{@code remove}方法,除非列表的{@code remove(int)}方法已覆盖。
    *<p>此实现可以在规范中所述的并发修改的面
    *对于(protected){@link#modCount}字段。
     * @return an iterator over the elements in this list in proper sequence
     */
    public Iterator<E> iterator() {
        return new Itr();
    }

    /**
     * {@inheritDoc}
     *
     * <p>This implementation returns {@code listIterator(0)}.
     *
     * @see #listIterator(int)
     */
    public ListIterator<E> listIterator() {
        return listIterator(0);
    }

    /**
     * {@inheritDoc}
     *
    *<p>此实现返回{@code ListIterator}接口,扩展了{@code迭代器}由{@code迭代器()}方法返回的接口。
    *{@code ListIterator}实现依赖于备份列表{@code get(int)},{@code set(int,E)},{@code add(int,E)}
    *以及{@code remove(int)}方法。<p>注意,此实现返回的列表迭代器将
    *抛出{@link unsportDoperationException}来响应
    *{@code remove}、{@code set}和{@code add}方法,除非列表的{@code remove(int)}、{@code set(int,E)和
    *{@code add(int,E)}方法被重写。
    *<p>此实现可以在
    *并发修改的面,如规范中所述
    *(受保护){@link\\modCount}字段。
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public ListIterator<E> listIterator(final int index) {
        rangeCheckForAdd(index);

        return new ListItr(index);
    }

    private class Itr implements Iterator<E> {
        /**
         * Index of element to be returned by subsequent call to next.
         */
        int cursor = 0;

       /**
       *最近对下一个或的调用返回的元素的索引上一个。如果此元素被调用删除,则重置为-1移除。
        */
        int lastRet = -1;

        /**
         * The modCount value that the iterator believes that the backing
         * List should have.  If this expectation is violated, the iterator
         * has detected concurrent modification.
         */
        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();
        }
    }
 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();
            }
        }
    }

在这里插入图片描述

subList 操作

返回的是父集合的一部分视图 也就是 还是操作的原来那个集合,只是因为 指针限制,所以操作的,指针区间的那部分。
new 一个SubList 对象,并在提供 add 方法 或者remove方法,set等方法, 将原有的集合持有着,后续操作

 /**
     * {@inheritDoc}
     *
    *<p>这个实现返回一个包含子类的列表{@code AbstractList}。子类在私有字段中存储
    *备份列表中子列表的偏移量,子列表的大小(在其生命周期内可能会发生变化)和
    *{@code modCount}支持列表的值。有两种变体子类,其中一个实现{@code RandomAccess}。
    *如果此列表实现{@code RandomAccess},则返回的列表将
    *是实现{@code RandomAccess}的子类的实例。
    *<p>子类的{@code set(int,E)},{@code get(int)},
    *{@code add(int,E)},{@code remove(int)},{@code addAll(int,
     *Collection)}和{@code removeRange(int,int)}方法
    *委托给备份抽象列表中相应的方法,在边界检查索引并调整偏移量之后。这个
    *{@code addAll(Collection c)}方法只返回{@code addAll(size,
    *c)}。
    *<p>方法{@CodeListIterator(int)}返回一个“包装器对象”在备份列表上的列表迭代器上,使用
    *备份列表上的相应方法。{@code iterator}方法
    *只返回{@code lisiterator()},和{@code size}方法只返回子类的{@code size}字段。
    *<p>所有方法首先检查支持列表等于其预期值,并抛出
     *{@code ConcurrentModificationException}如果不是。
     *
     * @throws IndexOutOfBoundsException if an endpoint index value is out of range
     *         {@code (fromIndex < 0 || toIndex > size)}
     * @throws IllegalArgumentException if the endpoint indices are out of order
     *         {@code (fromIndex > toIndex)}
     */
    public List<E> subList(int fromIndex, int toIndex) {
        return (this instanceof RandomAccess ?
                new RandomAccessSubList<>(this, fromIndex, toIndex) :
                new SubList<>(this, fromIndex, toIndex));
    }
class SubList<E> extends AbstractList<E> {
    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;
    }

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

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

    protected void removeRange(int fromIndexJava 集合深入理解  :AbstractCollection类

Java 集合深入理解 :HashMap之扩容 数据迁移

Java 集合深入理解 :集合框架体系图

深入理解java集合框架之---------Arraylist集合 -----添加方法

深入理解java集合框架之---------Arraylist集合 -----构造函数

《深入理解Java集合框架》系列文章