[集合类]源码解析3(Collection接口和AbstractCollection抽象类)

上一篇:[集合类] 源码解析2(Iterator的实现)

1. 概述

我们首先看一下Collection接口的javadoc,之后看一下在AbstractCollection中的实现。

2. Collection接口

下面是Collection中定义的接口列表,其中equals和hashCode是继承自Object,iterator方法是继承自Iterable,我们已经分析过,传送门:[集合类] 源码解析2(Iterator的实现)

在这里插入图片描述

下面是Collection接口,我们主要看一下接口方法注释。

public interface Collection<E> extends Iterable<E> {
  
		/*************************查询操作******************************/

    /**
     * 返回集合的元素数量,最大是Integer.MAX_VALUE
     */
    int size();

    /**
     * list没有元素,则返回true
     */
    boolean isEmpty();

    /**
     * 如果在list中至少存在一个e,满足(o==null ? e==null : o.equals(e)),则返回true
     * @throws ClassCastException 如果集合不接受指定元素的类型
     * @throws NullPointerException 如果特定元素是null,而集合不接受null
     */
    boolean contains(Object o);
  
    /**
     * 返回一个迭代器
     */
    Iterator<E> iterator();

  	/**
     * 按照一定顺序返回一个包含所有元素的数组,返回Object数组(范型会在编译期擦除),修改数组不会影响集合。
     * 是基于数组和基于集合之间的api之间的桥梁
     */
    Object[] toArray();

    /**
     * 返回一个包含所有元素的数组,保存到指定数组,返回数组的运行时类型是指定数组的运行时类型。
     * 如果数组length小于集合数量,则按照指定类型和该集合的大小分配新数组。
     * 如果数组length大于集合数量,则将剩余空闲元素设为null
     *
     * 如果集合保证迭代器返回元素顺序,这个方法必须以相同的顺序返回元素
     * 是基于数组和基于集合之间的api之间的桥梁,并且可以控制返回数组的运行时类型,在某些情况下可以节省分配成本
     * (猜想应该是如果要在数组后面追加内容,则可以直接分配最后需要的空间大小,否则第一次分配的空间则面临回收)
     * 
     * 集合转数组demo:
     *     String[] y = x.toArray(new String[0]);
     *
     * @throws ArrayStoreException 如果指定数组的运行时类型不是集合中每一个元素的父类型
     * @throws NullPointerException 如果指定数组是null
     */
    <T> T[] toArray(T[] a);

		/*************************修改操作******************************/

    /**
     * 添加成功,返回true
     * 如果集合拒绝添加一个元素,必须抛出异常,而不是返回false
     * @throws UnsupportedOperationException 当前的集合不支持add操作
     * @throws ClassCastException 指定元素的类阻止将其添加到此集合中
     * @throws NullPointerException 指定元素为null,并且集合不允许null元素
     * @throws IllegalArgumentException 元素的某些属性阻止它被添加到这个集合中
     * @throws IllegalStateException 由于插入限制,此时不能添加元素
     */
    boolean add(E e);

    /**
     * 如果集合存在任意一个e,对于o满足 (o==null ? e==null : o.equals(e),则移除e
     * 如果集合更改,返回true
     * @throws ClassCastException 如果集合不接受指定元素的类型
     * @throws NullPointerException 指定元素为null,并且集合不允许null元素
     * @throws UnsupportedOperationException 当前的集合不支持remove操作
     */
    boolean remove(Object o);


		/*************************批量操作******************************/

    /**
     * 如果集合包含所有指定元素返回true
     * @throws ClassCastException 如果集合不接受指定元素的类型
     * @throws NullPointerException 指定集合包含null,并且集合不允许null元素
     */
    boolean containsAll(Collection<?> c);

    /**
     * 将指定集合的所有元素添加到此集合,在操作中不能修改指定结合
     * @throws UnsupportedOperationException 当前的集合不支持addAll操作
     * @throws ClassCastException 指定集合中元素的类阻止将其添加到此集合中
     * @throws NullPointerException 指定集合包含null,并且集合不允许null元素
     * @throws IllegalArgumentException 如果集合中元素的某些属性阻止将其添加到此集合中
     * @throws IllegalStateException 由于插入限制,不是所有元素都可以在此时添加
     */
    boolean addAll(Collection<? extends E> c);

    /**
     * 删除此集合中包含指定集合的所有元素
     * @throws UnsupportedOperationException 当前的集合不支持removeAll操作
     * @throws ClassCastException 如果集合不接受指定元素的类型
     * @throws NullPointerException 指定集合包含null,并且集合不允许null元素
     */
    boolean removeAll(Collection<?> c);

    /**
     * 删除此集合中给定谓词的所有元素。迭代期间由谓词抛出的错误或运行时异常将传递给调用者。
     *
     * 实现要求:
     * 默认实现使用其iterator()遍历集合的所有元素。使用Iterator.remove()删除每个匹配的元素。
     * 如果集合的迭代器不支持删除,则将在第一个匹配的元素上抛出UnsupportedOperationException。
     * @param filter 对于要删除的元素,返回true的谓词
     * @return 如果任一元素被删除,返回true
     * @throws NullPointerException 如果指定过滤器为null
     * @throws UnsupportedOperationException 如果无法从该集合中删除元素
     * 如果无法删除匹配的元素,或者通常不支持删除,则实现可能会抛出此异常
     * @since 1.8
     */
    default boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        boolean removed = false;
        final Iterator<E> each = iterator();
        while (each.hasNext()) {
            if (filter.test(each.next())) {
                each.remove();
                removed = true;
            }
        }
        return removed;
    }

    /**
     * 从此集合中删除指定集合中不包含的所有元素
     * 集合改变,返回true
     * @throws UnsupportedOperationException 当前集合不支持retainAll操作
     * @throws ClassCastException 至少一个元素的类型与指定集合不兼容(可选)
     * @throws NullPointerException 当前集合存在至少一个null元素,并且指定元素不支持null
     */
    boolean retainAll(Collection<?> c);

    /**
     * 移除集合中所有元素,方法返回后集合为空
     * @throws UnsupportedOperationException 当前的集合不支持clear操作
     */
    void clear();

  
		/*************************比较和散列******************************/

    /**
     * 将指定的对象与此集合进行相等性比较。
		 * 集合接口没有对Object.equal的通用契约添加任何规定
		 * “直接”实现集合接口的程序员必须考虑是否选择重写Object.equals。
		 * 最简单的方法是依赖对象的实现,实现者可能希望实现一个“值比较”来代替默认的“引用比较”。
		 * 
		 * 该方法的一般约定规定,等号必须是对称的
		 * List.equal方法和Set.equal方法的契约中,List只与其他List相等,而Set与其他Set相等。
     */
    boolean equals(Object o);

    /**
     * 返回当前集合的hash码
     * 虽然Collection接口没有对方法的通用契约添加任何规定
     * 但程序员应该注意,任何覆盖equals方法的类也必须覆盖hashCode方法,以满足hashCode的通用契约。
     * 特别是 c1.equals(c2) 意味着 c1.hashCode()==c2.hashCode()
     */
    int hashCode();

    /**
     * stream方法,暂时不管
     */
    @Override
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, 0);
    }

    /**
     * stream方法,暂时不管
     */
    default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }

    /**
     * stream方法,暂时不管
     */
    default Stream<E> parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }
}

3. AbstractCollection

AbstractCollection我们主要看一下方法实现

public abstract class AbstractCollection<E> implements Collection<E> {

    // 唯一的构造函数,通常提供给子类调用
    protected AbstractCollection() {
    }

    // 两个抽象方法
    public abstract Iterator<E> iterator();

    public abstract int size();


    public boolean isEmpty() {
        return size() == 0;
    }

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

    public Object[] toArray() {
        // 这里的size只是估计值
        Object[] r = new Object[size()];
        Iterator<E> it = iterator();
        for (int i = 0; i < r.length; i++) {
            if (! it.hasNext())
              	// i还在循环,但是迭代器却没有下一个元素了,说明有并发remove操作,返回数组副本
                return Arrays.copyOf(r, i);
            r[i] = it.next();
        }
      	// i遍历结束,迭代器还有下一个,说明有并发add操作,扩容,并将剩余元素添加到数组中
      	// 否则,返回数组
        return it.hasNext() ? finishToArray(r, it) : r;
    }

    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        int size = size();
      	// 判断a的大小,不满足则利用反射创建新数组
        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++) {
          	// i还在循环,但是迭代器却没有下一个元素了,说明有并发remove操作
            if (! it.hasNext()) { 
              	// 如果没有创建新数组,最后一个元素置null,返回a
                if (a == r) {
                    r[i] = null; // null-terminate
                // 如果创建了新数组,并且当前数组长度大于a的长度,返回当前数组副本
                } else if (a.length < i) {
                    return Arrays.copyOf(r, i);
                // 如果创建了新数组,并且当前数组长度小于a的长度,将当前数组拷贝给a
                } else {
                    System.arraycopy(r, 0, a, 0, i);
                  	// 如果a数组没有用完,最后一个元素置null,返回a
                    if (a.length > i) {
                        a[i] = null;
                    } 
                }
                return a;
            }
            r[i] = (T)it.next();
        }
        // i遍历结束,迭代器还有下一个,说明有并发add操作,扩容,并将剩余元素添加到数组中
      	// 否则,返回数组
        return it.hasNext() ? finishToArray(r, it) : r;
    }

   /**
    * The maximum size of array to allocate.
    * Some VMs reserve some header words in an array.
    * Attempts to allocate larger arrays may result in
    * OutOfMemoryError: Requested array size exceeds VM limit
    */
  	// 最大数组数量 为 Integer.MAX_VALUE - 8
  	// 有的虚拟机实现,数组对象的头部会占用这8个字节
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

  	// 扩容,并将迭代器剩余元素添加到数组中
    @SuppressWarnings("unchecked")
    private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
      	// 当前数组索引,从数组尾开始
        int i = r.length;
        while (it.hasNext()) {
          	// cap为数组长度
            int cap = r.length;
          	// 当前数组索引等于数组长度,扩容
            if (i == cap) {
              	// 扩容大小 newCap = cap * 1.5 + 1
                int newCap = cap + (cap >> 1) + 1;
                // 保证数组最大长度
                if (newCap - MAX_ARRAY_SIZE > 0)
                    newCap = hugeCapacity(cap + 1);
              	// 扩容
                r = Arrays.copyOf(r, newCap);
            }
          	// 迭代,添加到数组中
            r[i++] = (T)it.next();
        }
        // 如果当前索引等于数组长度,说明数组刚好用完,返回数组。否则,按照当前长度返回数组副本
        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");
      	// 如果没超过MAX_ARRAY_SIZE,就是MAX_ARRAY_SIZE
      	// 超过MAX_ARRAY_SIZE,最大是Integer.MAX_VALUE
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

		// 通过Collection接口注释中已经说明UnsupportedOperationException
  	// 说明AbstractCollection不支持add方法
    public boolean add(E e) {
        throw new UnsupportedOperationException();
    }

  	// 移除o
    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;
    }

  	// 如果此集合中包含c中所有元素,返回true
    public boolean containsAll(Collection<?> c) {
        for (Object e : c)
            if (!contains(e))
                return false;
        return true;
    }

  	// 添加c中元素到此集合中
    public boolean addAll(Collection<? extends E> c) {
        boolean modified = false;
        for (E e : c)
            if (add(e))
                modified = true;
      	// 如果此集合改变,返回true
        return modified;
    }

  	// 对比retainAll,删除c中含有的元素
    public boolean removeAll(Collection<?> c) {
      	// 首先判断c不为空
        Objects.requireNonNull(c);
        boolean modified = false;
        Iterator<?> it = iterator();
        while (it.hasNext()) {
            if (c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
     		// 如果此集合改变,返回true
        return modified;
    }

		// 删除c中没有的元素
    public boolean retainAll(Collection<?> c) {
      	// 首先判断c不为空
        Objects.requireNonNull(c);
      	// 标志
        boolean modified = false;
        Iterator<E> it = iterator();
        while (it.hasNext()) {
          	// 使用contains方法,使用迭代器遍历此集合中的元素,如果c中不存在,删除
            if (!c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
      	// 如果此集合改变,返回true
        return modified;
    }

  	// 使用迭代器remove所有元素
    public void clear() {
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            it.next();
            it.remove();
        }
    }

  	// 使用StringBuilder
    public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for (;;) {
            E e = it.next();
          	// 当集合中添加了集合本身作为元素,会打印(this Collection)
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }

}

下一篇:[集合类]源码解析4(List接口和AbstractList抽象类)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值