ArrayList源码剖析

今天我们来探究一下ArrayList里面的究竟。。。本文采用Java8,下面是我自己结合源码对ArrayList的理解:
首先,在我们日常开发中经常也会用到ArrayList,为什么我们要使用ArrayList呢,而不使用其他的数据结构呢?
打开ArrayList源码:

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

首先得明白ArrayList是继承Abstract这个类的,同样又实现了List集合接口,这个类中有这些属性:
在这里插入图片描述
一眼先看出ArrayList的默认容量是10,ArrayList的底层也是基于elementDate[]这个数组实现的,数组的大小是由size属性决定。
我们一般new一个ArrayList都是调用ArrayList无参数构造函数:

	/**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
   /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; //初始化elementData 数组
    }

虽然初始化了,但是要注意此时这个数组是空的,不确定数组的大小,也就是Java8初始化数组,并没有指定数组的大小,更要注意java7源码有所不同,如下:

//调用有参数构造方法对ArrayList进行初始化
public ArrayList(int initialCapacity){
	super();
	if(initialCapacity<0){
		throw new IllegalArgumentException("Illegal Capacity:"+initialCapacity);
	}
	this.elementData=new Object[initialCapacity];
}
//无参数构造方法默认给定数组长度10
public ArrayList(){
	this(10);
}

**所以这是Java7和Java8之间很重要的一点:
Java7调用无参数构造方法会初始化数组大小,Java8不会初始化数组大小
我们继续往下看:
ArrayList底层就是数组,在初始化的时候也是在底层new的一个数组,但是arrayList数组的长度并不是在一开始就给你创建好的 我们继续往下看数组的add方法:

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
 }
   private static final int DEFAULT_CAPACITY = 10;
   private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    //真正的扩容,进行1,.5倍扩容
    private void grow(int minCapacity) {
        // 得到目前数组长度
        int oldCapacity = elementData.length;
        //给新的长度赋值:新容量等于老容量+老容量>>1(除以2)也就是1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        /对新数组进行拷贝 elementData老数组的数据 newCapacity新数组的数据
        //然后通过copyof进行拷贝,拷贝到一个新的数组中(第一次进入的时候就是创建一个为长度为10的数组而已 不要搞错了)这也是为什么说数组的增删效率低,因为实际上数组的增删实际上都是类似于这个的拷贝操作
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

总结:

  • Java7使用ArrayLIst创建对象时,若未指出ArrayList数组大小,则调用默认构造进行初始化,大小为10,而Java8使用ArrayLIst创建对象时,若未指出ArrayList数组大小,则不设置数组大小,在第一次add的时候设置。
  • 当调用add方法的时候,会与原集合数组大小比较,若不够,则进行1.5倍扩容,并拷贝数组传至新的扩容数组。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值