天天看点

JAVA集合框架2---AbstractCollection源码解析

        上一篇文章中我们讨论了java集合框架的根接口Collection的源码,这一篇中我们接着分析AbstractCollection类的源码。从类名称AbstractCollection我们就可以看出两点:1,该类应该是个抽象类;2,该类应该与Collection类有着某种联系。实际上AbstractCollection类的确是个抽象类,它提供了Collection接口的默认实现,实现的方式就是利用迭代器逐个操作。因此当我们想自己编写一个集合类时,直接继承AbstractCollection类即可,而不是实现Collection接口中的所有方法,这样可以加速开发(AbstractCollection类已经帮我们实现了部分方法,如果这些实现的方法满足我们的需求就可以直接拿来用即可,不用再自己去开发了。毕竟Collection接口中方法较多,直接实现肯定比继承AbstractCollection类的工作量大)。当需要实现一个不可变集合类的时候,程序员只需要实现size()和iterator方法里的hasNext和Next方法;当需要实现一个可变集合类时,还需要实现增加元素的方法和iterator里的remove方法。

        下面是AbstractCollection类的源码

//AbstractCollection是抽象类,提供了接口Collection的默认实现
public abstract class AbstractCollection<E> implements Collection<E> {
    //唯一的构造函数,一般用作子类的隐示调用。
    protected AbstractCollection() {
    }
    //返回一个迭代器,关于迭代器的讲解见下面
    public abstract Iterator<E> iterator();
    //Collection接口中的方法,返回集合元素的大小
    public abstract int size();
    //判断集合是否为空的默认实现
    public boolean isEmpty() {
        return size() == 0;
    }
    //判断集合是否包含对象o的默认实现
    public boolean contains(Object o) {
        Iterator<E> it = iterator();
        if (o==null) {//当o为null时
            while (it.hasNext())
                if (it.next()==null)
                    return true;
        } else {
            while (it.hasNext())
                if (o.equals(it.next()))
                    return true;
        }
        return false;
    }
    //将集合转化为数组的默认实现,通过迭代器遍历集合。在遍历集合的时候,集合的结构可能被改变了(如果集合容许的话)
    //在并发操作时,集合元素的个数可能不等于最初size()返回的大小
    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;
    }
    //返回具体类型的数组
    public <T> T[] toArray(T[] a) {
        // Estimate size of array; be prepared to see more or fewer elements
        int size = size();
        //如果传入数组的长度大于等于集合的大小则将集合元素填充到数组a中,否则通过反射生成一个大小是size的数组,使用这个数组来容纳集合的元素
        T[] r = a.length >= size ? a :
                  (T[])java.lang.reflect.Array
                  .newInstance(a.getClass().getComponentType(), size); // 为什么使用反射,不直接new一个呢? 不容许使用泛型数组!!!
        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) {  // 此时集合中的元素减少了,判断原数组a能否容下集合元素。
                    return Arrays.copyOf(r, i);
                } else {
                    System.arraycopy(r, 0, a, 0, i);  //原数组a可以容纳下集合元素了,直接使用原数组a。
                    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;
    }
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    //私有函数,调用toArray()函数时,当集合中元素增加时调用
    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;//扩容为原来的1.5倍,+1是为了防止cap = 0
                // 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异常
    public boolean add(E e) {
        throw new UnsupportedOperationException();
    }
    //删除对象o
    public boolean remove(Object o) {
        Iterator<E> it = iterator();
        if (o==null) {//当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中的所有元素
    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;
        return modified;
    }
    //删除包含集合c中元素的所有元素
    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);//确保c不为null
        boolean modified = false;
        Iterator<?> it = iterator();
        while (it.hasNext()) {
            if (c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
        return modified;
    }
    //只保留是集合c中的元素
    public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);//确保c不为null
        boolean modified = false;
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            if (!c.contains(it.next())) {
                it.remove();
                modified = true;
            }
        }
        return modified;
    }
    //清空集合
    public void clear() {
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            it.next();
            it.remove();
        }
    }
}
           

其实AbstractCollection实现的方法都比较简单,对于contains,remove方法都是简单的调用迭代器来实现的,当然迭代器的具体实现需要子类去完成。对于bulk opreation 操作就选循环的调用单词操作:比如addAll就是循环的调用add方法。

下面是迭代器的讲解:

接口Iterable源码:

public interface Iterable<T> {
    Iterator<T> iterator();
}
           

只有一个函数iterator(),返回Iterator接口对象,Iterator源码如下:

public interface Iterator<E> {
    boolean hasNext();
    E next();
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}
           

hasNext():当集合中还有元素是返回true,也就是说还没有遍历完集合。

next():返回下一个元素。

remove():需要子类自己实现(功能是:删除最后一次返回的元素,该方法必须在next之后调用,且每个next方法后只能调用一次remove()函数)。

使用迭代器的好处就是:实现了数据的实际组织方式和数据的迭代遍历相分离,需要访问容器元素的代码只需要一个Iterator接口的引用,不需要关注数据的实际组织方式(数组、链表或者树),可以使用一致和统一的方式访问。