AbstractCollection抽象类

第1部分 AbstractCollection抽象类介绍

AbstractCollection简介
AbstractCollection实现了Collection的绝大多数方法,只保留size和迭代器获取两个方法。
AbstractCollection大部分函数使用了迭代器遍历的方式来实现,而具体迭代方式交给子类实现。

AbstractCollection构造函数

修饰语和返回类型 方法 描述
protected AbstractCollection() 默认构造函数

AbstractCollection常用API

修饰语和返回类型 自身方法 描述
private static <T> T[] finishToArray(T[] r, Iterator<?> it)
private static int hugeCapacity(int minCapacity)
抽象方法
abstract Iterator<E> iterator() 获取迭代器
abstract int size() 获取集合容量

如图,按ctrl+o,单机类名就可以看到类的方法属性,其中A表示抽象函数Abstract,三角形表示继承于父类,S表示静态Static,F表示final。从中我们可以了解到,AbstractCollection实现了Collection中大部分方法(只标三角形,没标记A的方法),而为子类保留了两个抽象函数。
在这里插入图片描述
图1 方法列表

还有一个了解抽象类保留了几个抽象方法的方式是,继承它,让编译器去找。
在这里插入图片描述
图2 AbstractCollection留下的抽象方法

第2部分 AbstractCollection数据结构

AbstractCollection的继承关系

java.lang.Object
   ↳     
   
public abstract class AbstractCollection<E> implements Collection<E> {}

AbstractCollection的关系图
在这里插入图片描述
图1 AbstractCollection的关系图

第3部分 AbstractCollection源码解析(基于JDK-8u201)

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

    protected AbstractCollection() {
    }

    public abstract Iterator<E> iterator();
    public abstract int size();
    
    //直接判断现有元素是不是为0
    public boolean isEmpty() {
        return size() == 0;
    }

    public boolean contains(Object o) {
    	//获取迭代器
        Iterator<E> it = iterator();
        //根据o是否为null两种方式判断
        if (o==null) {
            while (it.hasNext())
            	//null的根据地址去比较
                if (it.next()==null)
                    return true;
        } else {
            while (it.hasNext())
            	//非null的根据等价性比较
                if (o.equals(it.next()))
                    return true;
        }
        return false;
    }

    public Object[] toArray() {
        // Estimate size of array; be prepared to see more or fewer elements
        //创建容量大小的Object数组
        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
            r[i] = it.next();
        }
        return it.hasNext() ? finishToArray(r, it) : r;
    }

	//将元素拷贝到数组a中
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        // Estimate size of array; be prepared to see more or fewer elements
        int size = size();
        //如果a的长度小于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) {
                	//a的长度不够,截断,将r的长度缩短为i,此时返回的是r
                    return Arrays.copyOf(r, i);
                } else {
                	//a的长度够用,将r的前i个元素拷贝到a,后面返回的是a
                    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;
    }

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

	//r长度不够,迭代器里还有元素
    @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) {
            	//扩容,增加原本的1/2容量,但是最后会截断,这里是为了减少扩容次数
                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
        //截断,将r的长度缩短为i
        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;
    }
	//默认不支持增加元素,因此子类需要增加元素的,要重写此方法
    public boolean add(E e) {
        throw new UnsupportedOperationException();
    }
    
    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;
    }

    public boolean containsAll(Collection<?> c) {
        for (Object e : c)
            if (!contains(e))
                return false;
        return true;
    }

    public boolean addAll(Collection<? extends E> c) {
    	//有一个元素添加成功了,则返回,更改过标志
        boolean modified = false;
        for (E e : c)
            if (add(e))
                modified = true;
        return modified;
    }
	
    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;
    }

    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();//如果c集合不包含迭代器里的元素,将迭代器里该元素移除掉
                modified = true;
            }
        }
        return modified;
    }
	//用迭代器将元素全部移除掉
    public void clear() {
        Iterator<E> it = iterator();
        while (it.hasNext()) {
            it.next();
            it.remove();
        }
    }
	
    public String toString() {
        Iterator<E> it = iterator();
        //迭代器为空,直接返回"[]"
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        //最终返回‘[元素a, 元素b, ...]’
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())//没元素了添加']',并返回字符串
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }
}

从上面的源码中,可以发现,除了拷贝的函数,其他基本都是通过迭代器来遍历元素。这是一种类似模板方法的设计模式,因为这个迭代器是子类实现的,遍历方式自然是由子类来决定,而父类的遍历,不需要管子类如何实现。

拷贝的方法涉及到的内容会比较深,下面会将它们拿出来解释下。

扫描二维码关注公众号,回复: 10525081 查看本文章

Arrays.copyOf(r, i)

@SuppressWarnings("unchecked")
    public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }

调用重载方法,根据名字,参数含义是,原数组,新的长度,数组类型

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        //类型如果是Object[],直接用new的方式创建长度为newLength的Object数组
        //否则,通过反射的方式,创建长度为newLength的newType类型数组
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        //将original中元素拷贝到copy中,拷贝长度为两者的最小值
        //也就是说,如果newLength比原数组小,那么数组后面的元素会被丢弃掉
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

至于两外两个函数,也就是System.arraycopy和Array.newInstance,实际上都是调用native的方法,也就是其他语言写的了

private static native Object newArray(Class<?> componentType, int length)
        throws NegativeArraySizeException;

public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

对于其他语言写的,不必深究,知道含义就行,当成普通的API使用。

发布了16 篇原创文章 · 获赞 0 · 访问量 289

猜你喜欢

转载自blog.csdn.net/kubiderenya/article/details/105331124