ArrayList源码分析(1.7.0_80)

定义

public class ArrayList<E> extends AbstractList<E>  implements List<E>, RandomAccess, Cloneable, java.io.Serializable

底层实现:数组

  • AbstractList 实现List的基本操作
  • List 定义List的基本方法
  • RandomAccess 一种标志位,类似于clone标志,作用:
    JDK中说的很清楚,在对List特别是Huge size的List的遍历算法中,要尽量来判断是属于RandomAccess(如ArrayList)还是Sequence List (如LinkedList),因为适合RandomAccess List的遍历算法,用在Sequence List上就差别很大,常用的作法就是:
    要作一个判断:
    if (list instance of RandomAccess) {
    for(int m = 0; m < list.size(); m++){}
    }else{
    Iterator iter = list.iterator();
    while(iter.hasNext()){}
    }
    参考这里

属性

 private transient Object[] elementData;

transient :此字段是否可以被序列化
elementData : ArrayList底层实现数组,初始大小10

方法

trimToSize

 public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = Arrays.copyOf(elementData, size);
        }
    }

作用:重新定义数组初始化大小
modCount:list被改变次数,定义在iterator中,用以判断list是否被同步修改,所以ArrayList不是同步安全的,可以使用以下代码包装一次list使其成为同步安全的:

 List list = Collections.synchronizedList(new ArrayList(...)); 
/**
         * 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;

若两者不相等抛出ConcurrentModificationException异常
重新定义数组大小,只是用来定义数组的容量,不代表数组中有多少个元素,所以

  public ArrayList(int initialCapacity) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
    }

用以上方法初始化ArrayList不能初始化ArrayList大小,一般用来当ArrayList数据较大时使用,避免ArrayList底层数组替换。

add(E e)

在list末尾添加元素

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

ensureCapacityInternal:判断是否需要扩容并扩容,modCount自增1
elementData[size++] = e; 新增元素加入数组
扩容方法:

 private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1); 
        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);
    }

扩容:newCapacity = oldCapacity + (oldCapacity >> 1) 一次扩容一半,至于为什么每次扩容1.5倍,效率问题,扩容之后并将源数据copy到新数组中。

add(int index, E element)

在指定位置添加元素

 public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

rangeCheckForAdd: 检查下标是否越界
System.arraycopy:将数组中index至末尾数据右移,耗时

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

将数组src中以srcPos开始长度为length的数据复制到dest中,从destPos开始粘贴;

余下add方法都是以以上两种方法为基础

contains(Object o)

数组中是否包含o,正序查找

indexOf(Object o)

返回list中第一次出现o的下标,正序查找,无返回-1。

lastIndexOf(Object o)

     返回list从末尾第一次出现o的下标,逆序查找,无返回-1。

clone()

public Object clone() {
        try {
            @SuppressWarnings("unchecked")
                ArrayList<E> v = (ArrayList<E>) super.clone();
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError();
        }
    }

ArrayList的clone属于浅拷贝,从这句v.elementData = Arrays.copyOf(elementData, size);ArrayList的clone只是将原数组中数据的地址复制到新数组中

参考博文:
链接一
链接二

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值