ArrayList 源码解析(JDK1.7)

ArrayList 源码解析(JDK1.7)

ps: 我思考了一下…想要不要发这篇博客… 感觉作为一个初学者…发这种源码解析… 尤其当做学习记录这样的东西来做…感觉没有任何的重点可言… 不过思考了一下…反正估计也没人看 (狗头) 就发了吧

纯属个人 … emmm 萌新的学习经历- -

大伙凑着看看吧…如果有错 , 请指出…




ArrayList的层次结构

在这里插入图片描述


接口
Iterable (可迭代的)
public interface Iterable<T> {
    //没啥好说的..获得一个迭代器
    Iterator<T> iterator();
}

Collection (集合)
public interface Collection<E> extends Iterable<E> {
    int size();				//获得集合大小
    boolean isEmpty();      //判断是否为空
    boolean contains(Object o);  //判断集合内是否包含元素
    Iterator<E> iterator();	//获得集合的迭代器
    Object[] toArray();		//将集合转为Object数组
    <T> T[] toArray(T[] a);	//将结合转为T数组
    boolean add(E e);	//添加一个元素
    boolean containsAll(Collection<?> c);	//是否包括了另外一个集合 
    boolean addAll(Collection<? extends E> c); //添加另外一个集合的所有元素
    boolean retainAll(Collection<?> c);  //保留c集合中的所有元素
    void clear();	//将集合清空
    
    // Object的方法 重写
    boolean equals(Object o);
    int hashCode();
}

List (列表)
public interface List<E> extends Collection<E> {
    //省略了从Collection 扩展的一些接口
    //....
	boolean addAll(int index, Collection<? extends E> c);	//从index的位置处 插入一个集合
    
    E get(int index);	//通过index获得值
    E set(int index, E element);	//设置值(修改)
    void add(int index, E element);	//在某个位置插入一个值
    E remove(int index); //移除index位置的值
    int indexOf(Object o); //查找o元素在列表中的位置
    int lastIndexOf(Object o); //查找最后一个o出现的位置
    ListIterator<E> listIterator();	//获得列表的迭代器
    ListIterator<E> listIterator(int index); //获得从index开始的列表
    List<E> subList(int fromIndex, int toIndex);   //截取一个小的列表
}

Cloneable (可拷贝的)
public interface Cloneable {	//是个用于标记的接口
    //只有实现了这个接口的类..才可以使用Object.Clone() 方法(动态方法) 对象.clone()
}

Serializable (可序列化的)
public interface Serializable {
    //也是用于标记的接口..签名
    //实现了这个接口的类, 可序列化
}

RandomAccess (随机访问)
public interface RandomAccess {
    //也是一个标记接口...用于加速随机访问..
    //用于底层的优化..
}

抽象类
AbstractCollection(抽象的集合)
public abstract class AbstractCollection<E> implements Collection<E> {
	//抽象类 ...没啥好说的感觉... 主要是实现了 Collection的绝大部分方法..除了 iterator 和 size 方法没实现
    //这里就分析一下它的private方法相关的东西 (以及 调用了这些方法的方法)
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;	//注意..列表的容量最大值是不允许超过 Integer.MAX_VALUE - 8 ...原因是 说 有些VM 中会在列表里面加入一些header work..可能会占用一些..
    
    public Object[] toArray() {
        // Estimate size of array; be prepared to see more or fewer elements
        Object[] r = new Object[size()];
        // 设计这个的时候...设计者的想法可能 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();
        }
        //走到这里的条件是 r的大小 >= 列表的大小
        //如果r的大小等于列表的大小..就会返回r
        //否则就是返回 finishToArray方法.
        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();
        T[] r = a.length >= size ? a :
                  (T[])java.lang.reflect.Array
                  .newInstance(a.getClass().getComponentType(), size);
        //这边也是类似上面的方法.. 首先判断 a元素大小够不够..如果不够 先扩容
        
        Iterator<E> it = iterator();

        /**
        如果 a 是 [1,2,3,4,5,6]
        列表是 [2,3]
        最后的返回值 就是 a 为[2,3,null,4,5,6]...感觉好怪异
        总的来说..调用这个方法之后, 信任返回值比较好..传入值有时改有时不会改
        **/
        for (int i = 0; i < r.length; i++) {
            if (! it.hasNext()) { // 如果列表的值 是 数组小...
                if (a == r) {		//a原本就比估计的要大
                    r[i] = null; //最后一个元素设置为null...
                } else if (a.length < i) {		//r是调用反射生成的.. a的大小 < 列表的大小元素大小
                    return Arrays.copyOf(r, i);	//压缩掉r的大小
                } else {			//我觉得这种情况就很怪异
                    //r 是通过反射生成的..r的大小应该就是列表大小...能到这里, 就说明了 列表的大小 < r的大小
                    //这个分支是 a的大小 >= 列表元素大小
                   	//总结起来就是 : 调用的时候 a的大小 < 列表元素大小
                    //中间发生了未知的情况造成 列表元素疯狂下降..下降到 a的大小 > 列表元素大小
                    System.arraycopy(r, 0, a, 0, i);
                    if (a.length > i) {
                        a[i] = null;
                    }
                }
                return a;
            }
            r[i] = (T)it.next();
        }
        //与上一个方法同理...
        return it.hasNext() ? finishToArray(r, it) : r;
    }
    
    /*
    进入这个方法的原因是 列表的实际元素数量 比 r要大
    首先保留i 也就是index 下标..从r的第i个元素开始填充
    然后将r进行扩容...遵照list的扩容方式.. 1.5倍的扩容
    **/
    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;
    }
}

AbstractList (抽象的列表)
//开始慢慢复杂
//在抽象集合中没有实现的2个方法 . 在这里类中 实现了 具体的获得迭代器的方法
// list 接口中的 get(int index) 方法没有实现
// 当然 在这个类中. 其他的一些增删改(list接口中)的操作 都是 抛出UnsupportedOperationException的 , 只能get..虽然没有实现
//但是 它新加了自己的一些remove方法...
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
    //已经被实现的方法..这里都不介绍了 . 具体抽出一些新加入的东西
    protected transient int modCount = 0; // 这个属性 记录着 集合的修改次数..主要用于 迭代器在遍历的时候 检测集合是否发生过修改...
    
    /**
    这个方法的意思么  就是移除这个区间里的元素.. 主要的关注点在于它的 迭代器的实现
    **/
    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() {
        return listIterator(0);
    }
    public ListIterator<E> listIterator(final int index) {
        rangeCheckForAdd(index);

        return new ListItr(index);
    }
    
    //实现了可迭代器的接口..具有迭代的能力
    private class Itr implements Iterator<E> {
        int cursor = 0;	  //游标..标记着 下一个遍历的元素下标
        
		//在代码中也能看出..记录着 cursor的上一值
        int lastRet = -1;	//最后一次调用 next 或者 previous 返回的下标 如果发生了remove 这个值又会变成-1	

        int expectedModCount = modCount;	//用来检测集合是否发生了值的变化.. 保证了在集合迭代的过程中不会发生改变

        public boolean hasNext() {	//是否有下一个..元素
            return cursor != size();
        }

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

        //移除元素 ...虽然最后还是调用的 AbstractList的remove 方法
        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.remove(lastRet);
                if (lastRet < cursor)
                    cursor--;
                lastRet = -1;		// 这里也就意味着 不能连续2次 remove
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }

        final void checkForComodification() {		//集合是否发生了修改
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }
    
    
    /**
    	列表的迭代器实现.. 看这里继承了一个 叫做Itr的类
    	这个类 也是其中一个内部类..就在上方
    	在能够迭代的基础上 还实现了 列表的迭代器..这个迭代器..又能向后 又能向前
    	还能够支持 set  和 add方法
    **/
    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();
            }
        }
    }
    
    //这个方法也是来自 list接口的 获得一段 子列表.. 里面涉及了2个类 (下面2个)
    public List<E> subList(int fromIndex, int toIndex) {
        return (this instanceof RandomAccess ?
                new RandomAccessSubList<>(this, fromIndex, toIndex) :
                new SubList<>(this, fromIndex, toIndex));
    }
}

//普通的子列表
/**
	大局浏览一下代码...
	发现并没有真实的再去取一段列表
	而是使用了源列表之后, 限定了一段区间...
	获取方式 使用 index + 偏移量的形式获取
*/
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);
    }

    public int size() {
        checkForComodification();
        return size;
    }

    public void add(int index, E element) {
        rangeCheckForAdd(index);
        checkForComodification();
        l.add(index+offset, element);
        this.modCount = l.modCount;
        size++;
    }

    public E remove(int index) {
        rangeCheck(index);
        checkForComodification();
        E result = l.remove(index+offset);
        this.modCount = l.modCount;
        size--;
        return result;
    }

    protected void removeRange(int fromIndex, int toIndex) {
        checkForComodification();
        l.removeRange(fromIndex+offset, toIndex+offset);
        this.modCount = l.modCount;
        size -= (toIndex-fromIndex);
    }

    public boolean addAll(Collection<? extends E> c) {
        return addAll(size, c);
    }

    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);
        int cSize = c.size();
        if (cSize==0)
            return false;

        checkForComodification();
        l.addAll(offset+index, c);
        this.modCount = l.modCount;
        size += cSize;
        return true;
    }

    public Iterator<E> iterator() {
        return listIterator();
    }

    public ListIterator<E> listIterator(final int index) {
        checkForComodification();
        rangeCheckForAdd(index);

        return new ListIterator<E>() {
            private final ListIterator<E> i = l.listIterator(index+offset);

            public boolean hasNext() {
                return nextIndex() < size;
            }

            public E next() {
                if (hasNext())
                    return i.next();
                else
                    throw new NoSuchElementException();
            }

            public boolean hasPrevious() {
                return previousIndex() >= 0;
            }

            public E previous() {
                if (hasPrevious())
                    return i.previous();
                else
                    throw new NoSuchElementException();
            }

            public int nextIndex() {
                return i.nextIndex() - offset;
            }

            public int previousIndex() {
                return i.previousIndex() - offset;
            }

            public void remove() {
                i.remove();
                SubList.this.modCount = l.modCount;
                size--;
            }

            public void set(E e) {
                i.set(e);
            }

            public void add(E e) {
                i.add(e);
                SubList.this.modCount = l.modCount;
                size++;
            }
        };
    }

    public List<E> subList(int fromIndex, int toIndex) {
        return new SubList<>(this, fromIndex, toIndex);
    }

    private void rangeCheck(int index) {
        if (index < 0 || index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

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

    private void checkForComodification() {
        if (this.modCount != l.modCount)
            throw new ConcurrentModificationException();
    }
}

//实现方式与 子列表相同....就是再次获取 子列表稍微不一样
class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
    RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) {
        super(list, fromIndex, toIndex);
    }

    public List<E> subList(int fromIndex, int toIndex) {
        return new RandomAccessSubList<>(this, fromIndex, toIndex);
    }
}

正餐 ArrayList (正主)

这里就不把整个类代码抓起来逐行看了…(代码比较长)…

对于一个类…我喜欢先从成员变量…属性…来看… 假设一些成员变量的作用…方法里使用到之后就能确定是否正确


成员变量

让我们先来看 它的成员变量

private static final int DEFAULT_CAPACITY = 10;			//默认的容量大小
private static final Object[] EMPTY_ELEMENTDATA = {};   //可能
private transient Object[] elementData;	//底层使用的是 Object[] 数组来存储元素
private int size;	//元素的大小
//这里 -8的原因 在上文中提到了...根据源码的解释..是说VM里面要在列表这个类型中 加入 header word..
//ps : 具体啥情况- -我也不知道..
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;	 //数组最大的长度.

实例方法
public ArrayList(int initialCapacity) {	//如果指定一个值进行初始化...就会直接进行初始化
    super();
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    this.elementData = new Object[initialCapacity];
}

public ArrayList() {
    super();
    //注意这里! 如果使用默认的话...不会先初始化!!!!! 会先使用一个空的数组进行标记..然后在第一次add的时候,扩容
    this.elementData = EMPTY_ELEMENTDATA;
}

public ArrayList(Collection<? extends E> c) {	//可以带一个集合进来
    elementData = c.toArray();
    size = elementData.length;
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    if (elementData.getClass() != Object[].class)
        elementData = Arrays.copyOf(elementData, size, Object[].class);
}

如果把每个方法都拿出来分析…就有些冗余了…

重要方法

// add

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  //主要是这个方法... 涉及了扩容机制
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == EMPTY_ELEMENTDATA) {		//如果使用默认方法构造..第一次会进入这里
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    ensureExplicitCapacity(minCapacity);
}

//明确是否要扩容   参数传入是 add之后的容量大小
private void ensureExplicitCapacity(int minCapacity) {
    modCount++;	//可能会涉及数组的结构变化...因此要改变当前的修改值..如果有迭代器正在遍历..
    //迭代器将会抛出错误
   
    // overflow-conscious code
    if (minCapacity - elementData.length > 0) // 如果当前容量不满足了..就需要发生扩容
        grow(minCapacity);
}

//扩容
private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);		//这里也是重要的地方.以原来1.5倍的大小进行扩容
    if (newCapacity - minCapacity < 0)	//如果扩容之后还是不满足数量的增长..就增长到 需要的数量
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)  //如果扩容超过了最大值..
        newCapacity = hugeCapacity(minCapacity);	//尝试容量能否下降下来..不能就爆了
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

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

// 可以让用户主动 更改 列表的容量的2个方法 trimTosizeensureCapacity(int)

//没啥好说的..主动扩容到 minCapacity 加上一点点小判断.
public void ensureCapacity(int minCapacity) {
    int minExpand = (elementData != EMPTY_ELEMENTDATA)
        ? 0
        : DEFAULT_CAPACITY;

    if (minCapacity > minExpand) {
        ensureExplicitCapacity(minCapacity);
    }
}

//主动减少容量
public void trimToSize() {
    modCount++;
    if (size < elementData.length) {
        elementData = Arrays.copyOf(elementData, size);
    }
}

// 用于 对象流的 writeObjectreadObject

这俩东西 我当时看的也是很蒙的… 发现没有方法调用这俩方法… 又是private的…

一番百度才知道…这是 使用在 对象流里面的… 对象流 会自动通过反射 调用这两个类…

出现这俩个类的原因是 : 存储数据的 private transient Object[] elementData; 是 transient关键字

不会被序列化… 当然不会被序列化也是考虑过的…因为 这个东西的大小通常比实际数据要大的多…

为了空间不被浪费

private void readObject(java.io.ObjectInputStream s)
    throws java.io.IOException, ClassNotFoundException {
    elementData = EMPTY_ELEMENTDATA;

    s.defaultReadObject();

    s.readInt();

    if (size > 0) {
        // be like clone(), allocate array based upon size not capacity
        ensureCapacityInternal(size);

        Object[] a = elementData;
        // Read in all elements in the proper order.
        for (int i=0; i<size; i++) {
            a[i] = s.readObject();
        }
    }
}

// 
private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
    // Write out element count, and any hidden stuff
    int expectedModCount = modCount;
    s.defaultWriteObject();

    // Write out size as capacity for behavioural compatibility with clone()
    s.writeInt(size);

    // Write out all elements in the proper order.
    for (int i=0; i<size; i++) {
        s.writeObject(elementData[i]);
    }

    if (modCount != expectedModCount) {
        throw new ConcurrentModificationException();
    }
}

内部的迭代器

和AbstractList中的迭代器实现方式 几乎相同 . 这里就不说了


SubList

因为ArrayList 是实现RandomAccess的 , 因此 和 AbstractList 比起来 默认就是 RandomAccess型


结束! …

又是摸鱼的一天 唉 苦逼

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值