Java集合源码分析(五)-AbstractCollection

137 阅读6分钟

「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战

源码

/**
 * 这个类提供 Collection 接口的框架实现,尽可能减少实现这个接口所需的努力
 *
 * 实现不可修改的集合,程序员仅需要继承这个类和提供 iterator 和 iterator 方法的实现(通过 iterator 方法返回的迭代器必须实现 hasNext 和 next)
 *
 * 实现可修改的集合,程序员必须另外重写这个类的 add 方法(否则抛出 UnsupportedOperationException),并且 iterator 返回的迭代器必须另外实现它的 remove 方法
 *
 * 程序员普遍应该提供一个 void(无参) Collection 构造器,像 Collection 接口规范中每一条建议
 *
 * 这个类中每个非抽象方法的文档详细的描述了它的实现
 * 如果集合允许更高效的实现,每一个非抽象方法可能被重写
 *
 * 这个类是 Java 集合框架的成员
 *
 * @author  Josh Bloch
 * @author  Neal Gafter
 * @see Collection
 * @since 1.2
 */
public abstract class AbstractCollection<E> implements Collection<E> {
    /**
     * 唯一构造函数(用于子类构造器调用,典型的含蓄)
     */
    protected AbstractCollection() {
    }

    // 查询操作

    /**
     * 返回这个集合包含的元素的迭代器
     *
     * @return 这个集合包含的元素的迭代器
     */
    public abstract Iterator<E> iterator();

    public abstract int size();

    /**
     * 这个实现返回 size() == 0
     */
    public boolean isEmpty() {
        return size() == 0;
    }

    /**
     * 这个实现会迭代集合中的元素,检查返回的每个元素和指定元素是否相等
     *
     * @throws ClassCastException
     * @throws NullPointerException
     */
    public boolean contains(Object o) {
        Iterator<E> it = iterator();
        if (o==null) {
            while (it.hasNext())
                if (it.next()==null)
                    return true;
        } else {
            while (it.hasNext())
                if (o.equals(it.next()))
                    return true;
        }
        return false;
    }

    /**
     * 这个实现返回一个包含这个集合的迭代器以相同顺序返回的所有元素数组,存储在数组的连续元素中,从索引 0 开始 
     * 如果集合允许在迭代时并发修改,可能会发生即使这个集合的大小在迭代的过程中改变,但返回数组的长度等于迭代器返回元素的数量的情况
     * method 方法仅被称为优化提示;即使迭代返回不同数量的元素,也会返回正确的结果
     * 
     * 这个方法相当于:
     *
     *  <pre> {@code
     * List<E> list = new ArrayList<E>(size());
     * for (E e : this)
     *     list.add(e);
     * return list.toArray();
     * }</pre>
     */
    public Object[] toArray() {
        // Estimate size of array; be prepared to see more or fewer elements
        Object[] r = new Object[size()];
        Iterator<E> it = iterator();
        for (int i = 0; i < r.length; i++) {
            if (! it.hasNext()) // fewer elements than expected
                return Arrays.copyOf(r, i);
            r[i] = it.next();
        }
        return it.hasNext() ? finishToArray(r, it) : r;
    }

    /**
     * 这个实现返回一个包含这个集合的迭代器以相同顺序返回的所有元素数组,存储在数组的连续元素中,从索引 0 开始 
     * 如果迭代器返回的元素太多,无法放入指定的数组,然后新分配的数组返回的元素的长度等于迭代器返回的元素的数量
     * 如果集合允许在迭代时并发修改,可能会发生即使这个集合的大小在迭代的过程中改变,但返回数组的长度等于迭代器返回元素的数量的情况
     * method 方法仅被称为优化提示;即使迭代返回不同数量的元素,也会返回正确的结果
     * 
     * 这个方法相当于:
     *
     *  <pre> {@code
     * List<E> list = new ArrayList<E>(size());
     * for (E e : this)
     *     list.add(e);
     * return list.toArray(a);
     * }</pre>
     *
     * @throws ArrayStoreException
     * @throws NullPointerException
     */
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        // Estimate size of array; be prepared to see more or fewer elements
        int size = size();
        T[] r = a.length >= size ? a :
                  (T[])java.lang.reflect.Array
                  .newInstance(a.getClass().getComponentType(), size);
        Iterator<E> it = iterator();

        for (int i = 0; i < r.length; i++) {
            if (! it.hasNext()) { // fewer elements than expected
                if (a == r) {
                    r[i] = null; // null-terminate
                } else if (a.length < i) {
                    return Arrays.copyOf(r, i);
                } else {
                    System.arraycopy(r, 0, a, 0, i);
                    if (a.length > i) {
                        a[i] = null;
                    }
                }
                return a;
            }
            r[i] = (T)it.next();
        }
        // more elements than expected
        return it.hasNext() ? finishToArray(r, it) : r;
    }

    /**
     * 要分配的最大数组大小
     * 一些虚拟机保留头信息在数组中
     * 尝试分配更大数组可能会导致 OutOfMemoryError:请求数组大小超过VM限制
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
     * 当迭代器返回比期望更多的元素,并从迭代器完成填充,使用 toArray 重新分配数组
     *
     * @param r 充满以前存储元素的数组
     * @param it 这个集合正在进行的迭代器
     * @return 包含给定数组的元素的数组,加上迭代器返回的任何元素,修剪到合适的大小
     *         further elements returned by the iterator, trimmed to size
     */
    @SuppressWarnings("unchecked")
    private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
        int i = r.length;
        while (it.hasNext()) {
            int cap = r.length;
            if (i == cap) {
                int newCap = cap + (cap >> 1) + 1;
                // overflow-conscious code
                if (newCap - MAX_ARRAY_SIZE > 0)
                    newCap = hugeCapacity(cap + 1);
                r = Arrays.copyOf(r, newCap);
            }
            r[i++] = (T)it.next();
        }
        // trim if overallocated
        return (i == r.length) ? r : Arrays.copyOf(r, i);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError
                ("Required array size too large");
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

    // 修改操作

    /**
     * 这个实现总是抛出 UnsupportedOperationException
     *
     * @throws UnsupportedOperationException
     * @throws ClassCastException
     * @throws NullPointerException
     * @throws IllegalArgumentException
     * @throws IllegalStateException
     */
    public boolean add(E e) {
        throw new UnsupportedOperationException();
    }

    /**
     * 这个实现会迭代查找指定元素的集合,如果找到这个元素,使用迭代器的 remove 方法从集合移除
     *
     * 请注意,如果通过这个集合的 iterator 方法返回的迭代器没有实现 remove 方法,并且这个集合包含指定对象,这个实现抛出 UnsupportedOperationException
     * 
     * @throws UnsupportedOperationException 
     * @throws ClassCastException 
     * @throws NullPointerException 
     */
    public boolean remove(Object o) {
        Iterator<E> it = iterator();
        if (o==null) {
            while (it.hasNext()) {
                if (it.next()==null) {
                    it.remove();
                    return true;
                }
            }
        } else {
            while (it.hasNext()) {
                if (o.equals(it.next())) {
                    it.remove();
                    return true;
                }
            }
        }
        return false;
    }

    // 批量操作

    /**
     * 此实现会迭代指定的集合,检查迭代器返回的每个元素,看看是否包含在指定集合
     * 如果所有元素都包含返回 true,否则 false
     *
     * @throws ClassCastException
     * @throws NullPointerException
     * @see #contains(Object)
     */
    public boolean containsAll(Collection<?> c) {
        for (Object e : c)
            if (!contains(e))
                return false;
        return true;
    }

    /**
     * 这个实现会迭代指定的集合,并且依次添加迭代器返回的每一个对象到这个集合
     *
     * 请注意,这个实现将抛 UnsupportedOperationException 除非重写 add(假设指定集合不为空)
     *
     * @throws UnsupportedOperationException
     * @throws ClassCastException
     * @throws NullPointerException
     * @throws IllegalArgumentException
     * @throws IllegalStateException
     *
     * @see #add(Object)
     */
    public boolean addAll(Collection<? extends E> c) {
        boolean modified = false;
        for (E e : c)
            if (add(e))
                modified = true;
        return modified;
    }

    /**
     * 这个实现会迭代这个集合,检查迭代器返回的每个元素,看看是否包含在指定集合
     * 如果包含,通过迭代器的 remove 方法从这个集合移除
     * 
     * 请注意,如果通过 iterator 方法返回的迭代器没有实现 remove 方法,并且这个集合与指定集合包含一个或多个相同的元素,这个实现将抛出 UnsupportedOperationException
     *
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws ClassCastException            {@inheritDoc}
     * @throws NullPointerException          {@inheritDoc}
     *
     * @see #remove(Object)
     * @see #contains(Object)
     */
    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        boolean modified = false;
        Iterator<?> it = iterator();
        while (it.hasNext()) {
            if (c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
        return modified;
    }

    /**
     * 这个实现会迭代这个集合,检查迭代器返回的每个元素,看看是否包含在指定集合
     * 如果没有包含,通过迭代器的 remove 方法从这个集合移除
     *
     * 请注意,如果通过 iterator 方法返回的迭代器没有实现 remove 方法,并且这个集合包含一个或多个不在指定集合存在的元素,这个实现将抛出 UnsupportedOperationException
     *
     * @throws UnsupportedOperationException
     * @throws ClassCastException
     * @throws NullPointerException
     *
     * @see #remove(Object)
     * @see #contains(Object)
     */
    public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        boolean modified = false;
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            if (!c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
        return modified;
    }

    /**
     * 这个实现会迭代这个集合,使用 Iterator.remove 操作移除每一个元素
     * 大部分实现将可能选择重写这个方法提高效率
     *
     * 请注意,如果迭代器根据这个集合的 iterator 方法没有实现 remove 方法,并且这个集合不是空,将抛出 UnsupportedOperationException
     *
     * @throws UnsupportedOperationException 
     */
    public void clear() {
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            it.next();
            it.remove();
        }
    }

    //  字符串转换

    /**
     * 返回这个集合的字符串表现
     * 字符串表现形式由一列集合元素根据迭代器按顺序组成返回,用方括号括起来("[]")
     * 相邻的元素被字符 "," 分隔
     * 元素被 String#valueOf(Object) 转换为字符串
     * 
     * @return 这个集合的字符串表现
     */
    public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }
}

总结

  • 查询操作
    • public boolean isEmpty():判断 size() == 0
    • public boolean contains(Object o):是否包含某个元素
    • public Object[] toArray():转成数组
    • public <T> T[] toArray(T[] a):转成数组
  • 修改操作
    • public boolean add(E e):添加
    • public boolean remove(Object o):移除
  • 批量操作
    • containsAll(Collection<?> c):判断是否包含
    • public boolean addAll(Collection<? extends E> c):批量添加
    • public boolean removeAll(Collection<?> c):批量删除,删除在指定集合的元素
    • public boolean retainAll(Collection<?> c):批量删除,保留在指定集合的元素
    • public void clear():全部删除
  • 字符串转换
    • public String toString():转字符串