ArrayList源码分析

分析ArrayList的源码可以帮助我们深入理解其内部实现和工作原理。下面是对Java中ArrayList的简要源码分析:

1. ArrayList的基本信息

ArrayList是Java集合框架中的一个类,它实现了List接口,是基于数组实现的动态数组。它允许快速随机访问元素,但在插入和删除元素时,性能可能会受到影响。

2. 主要成员变量

在ArrayList的源码中,有几个主要的成员变量:

private transient Object[] elementData;
private int size;
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
  • elementData: 这是一个Object类型的数组,用于存储ArrayList中的元素。
  • size: 这是ArrayList中当前元素的数量。
  • DEFAULT_CAPACITY: 默认的初始容量,当我们不指定初始容量时,ArrayList会默认使用这个值。
  • EMPTY_ELEMENTDATA: 空数组的默认值,用于在创建空ArrayList时节省内存。

3. 构造函数

ArrayList有多个构造函数,这里简单介绍一个最常见的构造函数:

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

在构造函数中,ArrayList会初始化一个空的数组(elementData),初始容量为DEFAULT_CAPACITY(即10)。

4. 添加元素:add方法

ArrayList的add方法用于向列表末尾添加元素,如果需要,会自动扩容。

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // 确保容量足够
    elementData[size++] = e;           // 将元素添加到数组末尾
    return true;
}
  • ensureCapacityInternal(int minCapacity): 这是一个私有方法,用于确保数组的容量足够以容纳指定的最小元素数。如果当前容量不够,则会进行扩容。
  • elementData[size++] = e;: 将元素添加到数组末尾,并将size(当前元素数量)递增。

5. 扩容机制:ensureCapacityInternal方法

当添加元素时,如果当前容量不足,就需要扩展数组。以下是ensureCapacityInternal方法的简化版本:

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    ensureExplicitCapacity(minCapacity);
}

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;  // 结构修改次数
    // 如果需要扩容
    if (minCapacity - elementData.length > 0) {
        grow(minCapacity);
    }
}

private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    // 扩展后的容量为旧容量的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 如果新容量仍不够,则直接使用所需的最小容量
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    // 将原数组的元素复制到新数组中
    elementData = Arrays.copyOf(elementData, newCapacity);
}
  • ensureCapacityInternal方法会根据需要进行扩容操作,如果当前容量不够,则调用grow方法进行扩容。
  • grow方法会创建一个新的更大容量的数组,并将原数组中的元素复制到新数组中。

6. 获取元素:get方法

ArrayList的get方法用于获取指定位置的元素:

public E get(int index) {
    rangeCheck(index);  // 检查索引是否合法
    return elementData(index);
}
  • rangeCheck(int index): 检查索引是否在有效范围内,如果不在范围内会抛出IndexOutOfBoundsException
  • elementData(int index): 返回指定索引位置的元素。

7. 删除元素:remove方法

ArrayList的remove方法用于删除指定位置的元素:

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; // help GC
    return oldValue;
}
  • System.arraycopy: 当删除元素后,将后续元素向前移动以填补空缺。
  • elementData[--size] = null;: 将末尾的元素置为null,帮助垃圾回收器进行回收。

8. 总结

ArrayList的源码分析帮助我们理解了其内部的工作机制,特别是如何实现动态扩展和元素的增删操作。它的基于数组的实现提供了快速的随机访问能力,但在频繁插入和删除操作时可能会有性能问题。对于更深入的理解和学习,建议查阅Java官方文档以及进一步阅读相关的数据结构和算法书籍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT洋少

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值