JDK源码阅读 0826 - 抽象集合

我们经常在代码中使用到List 、Set 、 Map ,也粗略看过一些实现类的源码解析。现在去看下抽象类集合中的方法与具体实现类有哪些不同。

public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> 
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> 
public abstract class AbstractMap<K,V> implements Map<K,V>

由上述代码可以看到 AbstractSet与 AbstractList 都继承了 AbstractCollection 然后去实现自己的方法 AbstractMap 单独实现Map的方法


AbstractList .png

AbstractSet.png

AbstractSet 只有较少的方法 除空构造函数之外 ,重写了Object 类 equal() 与 hashCode()


AbstractSetFunction.png

AbstractList 重写了较多的方法,其中大部分都是经常使用到的 包含 add(E) get(int) set(int,E) remove(int) indexOf(Object) clear() addAll(int Collection) 等等 其中add() remove() 等方法种其实并无具体实现,标注其实现类应抛出 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();
    }
AbstractListFunction.png

在去看ArrayList 源码时候,追溯扩展列表长度时偶然发现一个好玩的事情。 ensureCapacityInternal(int ) 逐步追溯发现ensureExplicitCapacity()中第一行为 操作modCount ,这个属性ArrayList 并不存在,存在于AbstractList中,且对其的注释准确解释了以前不理解的某些异常。

 private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
 private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    /**
     * The number of times this list has been <i>structurally modified</i>.
     * Structural modifications are those that change the size of the
     * list, or otherwise perturb it in such a fashion that iterations in
     * progress may yield incorrect results.
     *
     * <p>This field is used by the iterator and list iterator implementation
     * returned by the {@code iterator} and {@code listIterator} methods.
     * If the value of this field changes unexpectedly, the iterator (or list
     * iterator) will throw a {@code ConcurrentModificationException} in
     * response to the {@code next}, {@code remove}, {@code previous},
     * {@code set} or {@code add} operations.  This provides
     * <i>fail-fast</i> behavior, rather than non-deterministic behavior in
     * the face of concurrent modification during iteration.
     *
     * <p><b>Use of this field by subclasses is optional.</b> If a subclass
     * wishes to provide fail-fast iterators (and list iterators), then it
     * merely has to increment this field in its {@code add(int, E)} and
     * {@code remove(int)} methods (and any other methods that it overrides
     * that result in structural modifications to the list).  A single call to
     * {@code add(int, E)} or {@code remove(int)} must add no more than
     * one to this field, or the iterators (and list iterators) will throw
     * bogus {@code ConcurrentModificationExceptions}.  If an implementation
     * does not wish to provide fail-fast iterators, this field may be
     * ignored.
     */
    protected transient int modCount = 0;

简单的理解modCount这个属性就是 记录当前List 操作过的次数,如果更改列表大小或者其他方式更新列表进度 就会导致异常。如果需要提供快速失败的方法,就在add() 和 remove() 方法 中对列表进行结构修改,会抛出ConcurrentModificationExceptions 。
模拟一次, 在列表迭代中,如果对列表进行删除会首先触发ensureExplicitCapacity()modCount ++ ,在进行下次迭代时候触发checkForComodification() 比对expectedModCount 不同则抛出异常

 final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
 /**
         * 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;

在此之上,AbstractList中存在了几个内部类,用于迭代展示获取等情况,具体没有搞明白下次具体分析下。

AbstractMapFunction.png

AbstractMap 中实现的方法与AbstractList 基本相同,其中不同的只是关于Map 的键值映射关系,例如 KeySet() values() 等
在其中, remove方法中存在 Iterator 迭代其进行寻找并进行删除的方法, 这个迭代器 在AbstractList中也被用到,不过封装于内部实现类中 ListIterator 封装了三层。。。

    public V remove(Object key) {
        Iterator<Entry<K,V>> i = entrySet().iterator();
        Entry<K,V> correctEntry = null;
        if (key==null) {
            while (correctEntry==null && i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getKey()==null)
                    correctEntry = e;
            }
        } else {
            while (correctEntry==null && i.hasNext()) {
                Entry<K,V> e = i.next();
                if (key.equals(e.getKey()))
                    correctEntry = e;
            }
        }

        V oldValue = null;
        if (correctEntry !=null) {
            oldValue = correctEntry.getValue();
            i.remove();
        }
        return oldValue;
    }

  /**
     * {@inheritDoc}
     *
     * <p>This implementation returns a straightforward implementation of the
     * {@code ListIterator} interface that extends the implementation of the
     * {@code Iterator} interface returned by the {@code iterator()} method.
     * The {@code ListIterator} implementation relies on the backing list's
     * {@code get(int)}, {@code set(int, E)}, {@code add(int, E)}
     * and {@code remove(int)} methods.
     *
  */
  public ListIterator<E> listIterator(final int index) {
        rangeCheckForAdd(index);

        return new ListItr(index);
    }

    private class Itr implements Iterator<E> {  
//do something
XXX
}
private class ListItr extends Itr implements ListIterator<E>{
XXX
}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。