AbstractCollection和AbstractList源码简单分析

一、AbstractCollection

AbstractCollection是一个抽象类实现了Collection接口。源码如下,主要显示一些新增的方法和重写后有区别的方法。

package java.util;

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

	protected AbstractCollection() {
    }
    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 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();
                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('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }
}

可以看出,实现这个类需要重写size()方法和iterator()方法。调用add()会抛出抛出异常,并且在具体的方法中,则需要覆盖这个方法,并且调用类中的方法获取Iterator后,也需要实现hasNext()、next()和remove()方法(回头看javaAPI中的总结更规范)。这个类是一个中间类,该类提供了Collection接口的骨架实现,以尽量减少实现此接口所需的工作量,相比较,List接口定义了更多的集合方法,这就是抽象与实现的分离吗。
下面看几个比较稍复杂的方法:

toArray()

返回一个包含此集合中所有元素的数组。

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++) {
        	//(1)
            if (! it.hasNext()) // fewer elements than expected
                return Arrays.copyOf(r, i);//(2)
            r[i] = it.next();
        }
        //(3)
        return it.hasNext() ? finishToArray(r, it) : r;
}	

这个方法中应用了大量的判断来保证集合转数组赋值的准确性(多线程执行),这就指的是线程安全的方法吗?
逻辑分析下:
1.如果数组的大小等于迭代器遍历的次数相同,直接返回 步骤(3)的经过遍历赋值的数组r
2.如果数组的大小小于迭代器遍历的次数,走步骤(3)中的 finishToArray()
2.如果数组的大小大于迭代器遍历的次数,走步骤(2)中的 Arrays.copyOf()方法,对数组进行截断补充
看步骤(2)的Arrays.copyOf()方法:

public class Arrays {
...
@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")
        //(4)
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        //(5)
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

步骤(4)中如果该对象的类型是数组,则创建个newLength大小的数组,否则通过Array.newInstance中的newArray()方法创建个新的对象再转成数组(猜测是用反射创建对象呢)。最后通过System.arraycopy()将源数组赋值到目标数组中。
步骤(5)将原始数组赋值到新数组中,返回结果。
看步骤(3):

@SuppressWarnings("unchecked")
	 /**
     * 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
     */
     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
        int i = r.length;
        while (it.hasNext()) {
            int cap = r.length;
            if (i == cap) {//(6)
                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;
    }

该方法补充剩余的元素到数组中。
步骤(6)中为自定义的扩展当前数组的大小,以避免添加数据时引起数组越界异常。
其中:

//就是 1.5cap + 1
int newCap = cap + (cap >> 1) + 1;

这个确定数组大小值的方式应该也是效率最高的方式了。
注:虚拟机在数组中保留了一些头字,所以数组的最大值比int常量最大值减去8。

toArray(T[] a)

返回包含此集合中所有元素的数组; 返回的数组的运行时类型是指定数组的运行时类型。当参数数组大小大于原集合大小时,剩下的元素用null补充。

@SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        // Estimate size of array; be prepared to see more or fewer elements
        int size = size();
        //(1)
        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++) {
        	//(2)
            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;
    }

toArray()返回的是Object[]数组,而该方法返回的是参数类型的数组。
步骤(1):返回的数组大小取原集合大小与参数数组大小中的最大值。
大部分的逻辑和toArray()方法中的逻辑是一样的,在步骤(2)中更加详细的判断了可能出现的各种情况(我已经懵了)表明该方法是线程安全的,余下的元素用null补充。
举个ArrayList的例子:

ArrayList<String> testOne = new ArrayList<>();
testOne.add("1");
testOne.add("2");
testOne.add("3");
String[] testStringsOne = {"1","1"};
String[] testStringsTwo = {"6","6","6","6"};
String[] resArrayOne = testOne.toArray(testStringsOne);
String[] resArrayTwo = testOne.toArray(testStringsTwo);

resArrayOne中是[1,2,3]。resArrayTwo中是[1,2,3,null]。

其他

remove()方法可以移除空元素,toString()方法表明集合直接输出不是地址值,而是输出每个元素。

二、AbstractList

此类提供的骨干实现的List接口以最小化来实现该接口由一个“随机访问”数据存储备份所需的工作。
其中get和size方法为抽象方法,实例化对象需要重写方法,而调用add和set方法则会抛出异常,该类拓展了很多根据索引截取对象,和自定义迭代器更好的遍历列表实现功能。
AbstractList类中存在大量的内部类来实现具体的功能。

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
	...
	abstract public E get(int index);
	public E set(int index, E element) {
		throw new UnsupportedOperationException();
	}
	public int size() {
        checkForComodification();
        return size;
    }
	public int indexOf(Object o) {
		ListIterator<E> it = listIterator();
		if (o==null) {
	    	while (it.hasNext())
	        	if (it.next()==null)
	            	return it.previousIndex();
		} else {
	    	while (it.hasNext())
	        	if (o.equals(it.next()))
	            	return it.previousIndex();
		}
		return -1;
	}

	public int lastIndexOf(Object o) {
        ListIterator<E> it = listIterator(size());
        if (o==null) {
            while (it.hasPrevious())
                if (it.previous()==null)
                    return it.nextIndex();
        } else {
            while (it.hasPrevious())
                if (o.equals(it.previous()))
                    return it.nextIndex();
        }
        return -1;
    }
    protected transient int modCount = 0;
	private class Itr implements Iterator<E> {
        
        //由后续调用Next返回的元素的索引,光标
        int cursor = 0;

        //最近调用next或previous返回的元素的索引。如果通过调用remove删除此元素,则重置为-1。
        int lastRet = -1;

        /**
         * 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;

        public boolean hasNext() {
            return cursor != size();
        }
		//(1)
        public E next() {
            checkForComodification();
            try {
                int i = cursor;
                E next = get(i);
                lastRet = i;
                cursor = i + 1;
                return next;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }
		//(2)
        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.remove(lastRet);
                if (lastRet < cursor)
                    cursor--;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }
    
    private class ListItr extends Itr implements ListIterator<E> {
        ListItr(int index) {
            cursor = index;
        }

        public boolean hasPrevious() {
            return cursor != 0;
        }

        public E previous() {
            checkForComodification();
            try {
                int i = cursor - 1;
                E previous = get(i);
                lastRet = cursor = i;
                return previous;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

        public int nextIndex() {
            return cursor;
        }

        public int previousIndex() {
            return cursor-1;
        }

        public void set(E e) {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.set(lastRet, e);
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        public void add(E e) {
            checkForComodification();

            try {
                int i = cursor;
                AbstractList.this.add(i, e);
                lastRet = -1;
                cursor = i + 1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    }
}	

ListItr和Itr是AbsractList的内部类,分别实现了Iterator和ListIterator的迭代功能,来对AbsractList列表实现更多的功能。

add方法

	public boolean add(E e) {
        add(size(), e);
        return true;
    }
    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }
    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);
        boolean modified = false;
        for (E e : c) {
            add(index++, e);
            modified = true;
        }
        return modified;
    }
    private void rangeCheckForAdd(int index) {
        if (index < 0 || index > size())
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size();
    }

在列表中增加元素,实现添加元素的列表需要重写add()方法。

clear()

	public void clear() {
        removeRange(0, size());
    }
    protected void removeRange(int fromIndex, int toIndex) {
        ListIterator<E> it = listIterator(fromIndex);
        for (int i=0, n=toIndex-fromIndex; i<n; i++) {
            it.next();
            it.remove();
        }
    }
    public ListIterator<E> listIterator(final int index) {
        rangeCheckForAdd(index);
        return new ListItr(index);
    }

清空集合中的所有元素。
通过调用方法(1)Itr.next()和方法(2)Itr.remove()删除集合中的每一个元素,通过 cursor光标变量和lastRet标识位控制元素的删除,本质上还是在方法控制好cursor和lastRet的变量值,通过调用 get()方法和remove()方法逐个删除元素。

equals(Object o)

public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof List))
            return false;

        ListIterator<E> e1 = listIterator();
        ListIterator<?> e2 = ((List<?>) o).listIterator();
        while (e1.hasNext() && e2.hasNext()) {
            E o1 = e1.next();
            Object o2 = e2.next();
            if (!(o1==null ? o2==null : o1.equals(o2)))
                return false;
        }
        return !(e1.hasNext() || e2.hasNext());
    }

判断2个集合是否相等。
1.引用相同,集合的值相同,返回true。
2.不是List的一个实例,返回false。
3.遍历判断元素的值是否都相等,有一个元素不相等返回false,集合的大小是否都相等。
(其中:o1.equals(o2)方法,如果引用相同则返回true;该类型重写了equals方法例如String,Integer或其他自定义的类,值相同则返回true;其他大多数情况返回false)

indexOf(Object o)与lastIndexOf(Object o)

一个是从前往后遍历,一个是从后往前遍历(用hasPrevious()和previous()向前遍历),当出现该值时,返回索引值(索引值同样由ListItr中的变量cursor确定)否则返回-1

subList(int fromIndex, int toIndex)

返回此列表中指定的 fromIndex (含)和 toIndex之间的视图。

public List<E> subList(int fromIndex, int toIndex) {
    return (this instanceof RandomAccess ?
            new RandomAccessSubList<>(this, fromIndex, toIndex) :
            new SubList<>(this, fromIndex, toIndex));
}

其中SubList和RandomAccessSubList都是AbstractList的实现类,专门来实现截取后的列表的各种操作数据的功能。
部分代码如下:

class SubList<E> extends AbstractList<E> {
    private final AbstractList<E> l;
    private final int offset;
    private int size;

    SubList(AbstractList<E> list, int fromIndex, int toIndex) {
        if (fromIndex < 0)
            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
        if (toIndex > list.size())
            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
        if (fromIndex > toIndex)
            throw new IllegalArgumentException("fromIndex(" + fromIndex +
                                               ") > toIndex(" + toIndex + ")");
        //**************************
        l = list;
        //**************************
        offset = fromIndex;
        size = toIndex - fromIndex;
        this.modCount = l.modCount;
    }

    public E set(int index, E element) {
        rangeCheck(index);
        checkForComodification();
        return l.set(index+offset, element);
    }
    public E get(int index) {
        rangeCheck(index);
        checkForComodification();
        return l.get(index+offset);
    }
    ...
}

SubList类相当于列表截取后的包装对象,逻辑与AbtractList相同,只是在此基础上计算偏移量之后的值(fromIndex相当于偏移量,toIndex-fromIndex为新列表的大小)。
注:由于上图中代码中的

l = list;

所以修改subList()后的列表也会对原列表进行修改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值