ArrayList底层原理

Java的ArrayList底层原理

  在Java中,ArrayList是List接口的一个典型实现。它是一种动态数组,可以根据需要增长或缩小其容量。在内部,ArrayList使用一个数组来存储元素,这个数组的大小会根据需要动态调整。

1、 内部结构

1.1. 成员变量

ArrayList的内部结构主要由以下几个成员变量组成:

elementData:一个Object类型的数组,用于存储ArrayList中的元素。
size:一个int类型的变量,表示当前ArrayList中元素的数量。

 1.2 构造方法

ArrayList提供了多个构造方法,其中最常用的是无参构造方法,它会创建一个初始容量为0的ArrayList。其他构造方法可以指定初始容量,例如:
ArrayList<String> list = new ArrayList<>(10); // 创建一个初始容量为10的ArrayList

1.3扩容机制

当ArrayList的元素数量达到其容量时,ArrayList会自动扩容。扩容的方式如下:

 如果当前容量小于64,则新容量为当前容量的两倍加2。
 如果当前容量大于或等于64,则新容量为当前容量的1.5倍。

1.4.添加和删除操作

在ArrayList中,添加和删除操作的时间复杂度为O(1)。具体实现如下:

 添加操作:如果当前容量足够,则直接将元素添加到数组末尾;否则,先扩容,再将元素添加到数组末尾。
 删除操作:直接将要删除的元素后面的所有元素向前移动一位。

1.5性能分析

ArrayList的性能主要取决于其内部数组的扩容机制。在大多数情况下,ArrayList的性能表现良好,但在极端情况下,可能会出现频繁的扩容操作,导致性能下降。因此,在使用ArrayList时,应该尽可能避免频繁的扩容操作。

2、源码分析

2.1成员变量

transient Object[] elementData; // 存储元素的数组
private int size; // 当前元素数量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; // 数组的最大容量
private static final Object[] EMPTY_ELEMENTDATA = {}; // 空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 默认容量的空数组

2.2 构造方法

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

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

public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if (elementData.getClass() != Object[].class)
        elementData = Arrays.copyOf(elementData, size(), Object[].class);
    size = elementData.length;
}

2.3扩容机制
 

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

2.4添加和删除操作
 

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

public E remove(int index) {
    rangeCheck(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; // Let gc do its work

    return oldValue;
}

3、具体执行过程如下

第一次添加数据时:

添加第11个数据时就要进行扩容了:

4、总结

ArrayList 的源码实现主要包括成员变量、构造方法、扩容机制、添加和删除操作等部分。通过这些部分的实现,ArrayList 能够高效地存储和操作数据。在实际使用中,我们需要根据实际需求选择合适的容量,并尽量避免频繁的扩容操作,以提高程序的性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值