ArrayList底层分析

本文详细介绍了ArrayList的内部工作机制,包括其作为动态数组的特性、继承结构、属性与构造函数的实现。重点讲解了ArrayList的add方法和扩容机制,如grow方法如何在容量不足时按1.5倍进行扩容。此外,还提到了线程安全性和序列化支持。
摘要由CSDN通过智能技术生成

1.概述

ArrayList相当于是动态数组,底层使用Object[],可以存储任意数据类型,容量能够动态扩容,但是其线程不安全。

2.继承结构

 ArrrayList继承了一个抽象类AbstractList,三个接口Cloneable,Serializable,RandomAccess

  1. AbstractList用于抽象提取,内部抽取抽象方法,子类去具体实现,主要用于减少重复代码
  2. RandomAccess是标记型接口,表示这个类是可以快速访问
  3. Serializable表示这个类可以序列化
  4. Cloneable表示这个类支持克隆方法使用

3.属性与构造函数

    private static final long serialVersionUID = 8683452581122892189L;
    // 缺省容量
    private static final int DEFAULT_CAPACITY = 10;
    // 空对象数组
    private static final Object[] EMPTY_ELEMENTDATA = {};
    // 缺省空对象数组
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    // 元素数组
    transient Object[] elementData;
    // 实际元素大小,默认为0
    private int size;
    // 最大数组容量
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

主要包括数组容量size,默认的空对象数组

构造函数

1. 默认无参构造

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

初始化为默认空数组。

注意:此时我们创建的ArrayList对象中的elementData中的长度是1,size是0,当进行第一次add的时候,elementData将会变成默认的长度:10.

2. 有参构造 传入初始容量

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

对传入的容量进行分支判断  比较简单理解

3.Collection 为形参的构造函数

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

4.add方法

public boolean add(E e) {    
    //确定内部容量是否够了,size是数组中数据的个数,因为要添加一个元素,所以size+1,先判断size+1的这个个数数组能否放得下,就在这个方法中去判断是否数组.length是否够用了。
        ensureCapacityInternal(size + 1);  // Increments modCount!!
     //在数据中正确的位置上放上元素e,并且size++
        elementData[size++] = e;
        return true;
    }

add主要的执行逻辑如下:

  1. 确保数组已使用长度(size)加1之后足够存下 下一个数据
  2. 修改次数modCount 标识自增1,如果当前数组已使用长度(size)加1后的大于当前的数组长度,则调用grow方法,增长数组,grow方法会将当前数组的长度变为原来容量的1.5倍。
  3. 确保新增的数据有地方存储之后,则将新元素添加到位于size的位置上。
  4. 返回添加成功布尔值

确保添加的元素有地方存储,当第一次添加元素的时候this.size+1 的值是1,所以第一次添加的时候会将当前elementData数组的长度变为10:

5.grow方法

真正的进行扩容的地方

  • 新的容量为旧容量的1.5倍、

  • Arrays.copyof方法进行数组拷贝

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值