ArrayList源码剖析

构造函数:有3个构造函数
1)在jdk源码中ArrayList无参的构造函数,默认初始化大小是10;
2)带有指定大小参数的构造函数
3)带有集合参数的构造函数

一、确定ArrarList的容量
1、若ArrayList的容量不足以容纳当前的全部元素,设置新的容量 = (原始容量 * 3) / 2 + 1。
2、如果扩容后容量还是不够,则直接将minCapacity设置为当前容量。

    public void ensureCapacity(int minCapacity) { 
        // 将“修改统计数”+1,该变量主要是用来实现fail-fast机制的     
        modCount++;                  
        int oldCapacity = elementData.length;  
        // 若当前容量不足以容纳当前的元素个数,设置新的容量=“(原始容量x3)/2 + 1”  
        if (minCapacity > oldCapacity) {  
            Object oldData[] = elementData;    
            int newCapacity = (oldCapacity * 3)/2 + 1;  
            //如果还不够,则直接将minCapacity设置为当前容量  
            if (newCapacity < minCapacity)    
                newCapacity = minCapacity;    
            elementData = Arrays.copyOf(elementData, newCapacity);    
        }    
}

二、添加元素

    public boolean add(E e) {    
        ensureCapacity(size + 1);    // 确定ArrayList的容量大小
        elementData[size++] = e;    // 添加e到ArrayList中
        return true;    
    }
将Element添加到ArrayList的指定位置    
    public void add(int index, E element) {    
        if (index > size || index < 0)    
            throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);    
        ensureCapacity(size+1);          //确定ArrarList的容量   
        //将index位置及后面的元素都往后移一位
        System.arraycopy(elementData, index, elementData, index + 1, size - index);    
        elementData[index] = element;    //将e添加到index位置
        size++;    
    }

三、获取index位置的元素值

    public E get(int index) {    
        RangeCheck(index);    
        return (E) elementData[index];    
    }

四、设置index位置的值为element

  public E set(int index, E element) {    
        RangeCheck(index);    
        E oldValue = (E) elementData[index];    
        elementData[index] = element;    
        return oldValue;    
    }

五、删除ArrayList指定位置的元素

    public E remove(int index) {    
        RangeCheck(index);                  //检查索引index是否合理
        modCount++;    
        E oldValue = (E) elementData[index];    //保存要删除位置的元素
        int numMoved = size - index - 1;        //得到要移动的元素的个数
        if (numMoved > 0)    
            System.arraycopy(elementData, index+1, elementData, index, numMoved);    
        elementData[--size] = null;             //因为都往后移了一位,所以最后一个元素要置空    
        return oldValue;    
}
删除元素    
 public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
}     
    private void fastRemove(int index) {    
        modCount++;    
        int numMoved = size - index - 1;    
        if (numMoved > 0)         //从"index+1"开始,用后面的元素替换前面的元素。
            System.arraycopy(elementData, index+1, elementData, index, numMoved);  
        elementData[--size] = null;   //将最后一个元素设为nul   
}

六、ArrayList是否包含Object(o)

    public boolean contains(Object o) {    
        return indexOf(o) >= 0;    
    }

正向查找,返回元素的索引值

    public int indexOf(Object o) {    
        if (o == null) {    
            for (int i = 0; i < size; i++)    
                if (elementData[i]==null)    
                    return i;    
         } else {    
             for (int i = 0; i < size; i++)    
               if (o.equals(elementData[i]))    
                    return i;    
         }    
         return -1;    
        }
    }

七、返回ArrayList的Object数组

    public Object[] toArray() {    
        return Arrays.copyOf(elementData, size);    
    }

八、将集合c追加到ArrayList中

    public boolean addAll(Collection<? extends E> c) {    
        Object[] a = c.toArray();          //得到集合实际保存元素的数组
        int numNew = a.length;    
        ensureCapacity(size + numNew);  //确定添加集合后ArrayList的容量合理    
        System.arraycopy(a, 0, elementData, size, numNew);   //利用System.arraycopy方法将数组拷贝到ArrayList集合的数组中 
        size += numNew;    
        return numNew != 0;    
    }

分析ArrayList源码比较重要的几点总结:
1、ArrayList是如何确定容量的—->调用ensureCapacity方法。

2、ArrayList是基于数组的,所以获取元素和设置元素都是这样的形式:elementData[index],只需获取到数组索引就可以了。

3、在ArrayList源码中,大量使用了System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
src:源数组; srcPos:源数组要复制的起始位置; dest:目的数组; destPos:目的数组放置的起始位置; length:复制的长度。
比如ArrayList的增加、删除、将集合c追加到ArrayList中这三种操作,都使用了这个方法。

4、Arrays类的静态方法:copyOf(T[] original, int newLength)
original - 要复制的数组 ; newLength - 要返回的副本的长度 ; newType - 要返回的副本的类型
比如ArrayList的toArray()方法就使用了Arrays.copyOf方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值