ArrayList源码学习

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

ArrayList继承了AbstractList抽象类,实现了List、RandomAccess、Serialzable接口,其实AbstaactList已经实现过List接口了,ArrayList又实现一次,可能是为了规范吧。

我们来看一下它的字段信息

//默认容量为10
private static final int DEFAULT_CAPACITY = 10
//空的数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//默认容量为空的数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//数组
transient Object[] elementData;
//数组大小
 private int size;

它有一个入参为整型的构造方法,若传入值大于0,则创建传入值大小的数组,如果传入值为0,那么数组大小默认为0,否则将抛出IllegalArgumentException

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

一个入参为Collection类型的变量,很简单,先将其转化为数组,如果长度不为0,且不为空,那么就把这个数组复制到elementData中,否则初始大小为0

public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

 它还有一个无参构造方法,默认初始容量为0,DEFAULTCAPACITY_EMPTY_ELEMENTDATA 是一个空数组

 
 public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

在官方注释上标识数组初始容量为10是错的,这里下面会说

 public boolean add(E e) {
        //对数组大小进行检查,容量不足会进行扩容
        ensureCapacityInternal(size + 1);  
        elementData[size++] = e;
        return true;
    }
在不指定ArrayList大小时,默认初始容量为0,然后在add操作时,会对数组容量进行检查,若数组已不足以存放这一个数据,那么会进行扩容,
 
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//如果elementData是一个空数组,那么会将它扩容为大小为10的数组
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }
所以通常所说的初始容量为10,说的都是在执行第一次add操作之后,
get方法,因为java数组不允许越界,因此会先进行范围检查,然后返回数组元素。
 
 public E get(int index) {
        rangeCheck(index);
        return elementData(index);
    }

set方法,同样会检查是否越界,然后将数组元素

public E set(int index, E element) {
        rangeCheck(index);
        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }
remove方法,将指定索引的元素移除,国际惯例检查越界,将索引处值赋给中间变量oldValue用来返回,然后会将索引后的元素移动一个位置,
然是这样效率太低,因此,直接将后面的数组直接复制过去
 public E remove(int index) {
        rangeCheck(index);

        modCount++;
        E oldValue = elementData(index);

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }
这也是为什么ArrayList增删的速度较慢的原因,但是其查找速度快,因为毕竟底层是数组嘛!


 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值