前言

大家好,我是chowley,不知各位在面试中,是否被问过 ‘读没读过相关框架的源码?’ 这个经典问题?我最近就遇到了,虽然我之前读过,但这玩意干读不进味啊

今天我就来讲讲ArrayList,这个白家长谈的经典数据结构的扩容机制!

ArrayList

在Java的集合框架中,ArrayList是一个非常常用的动态数组实现。了解其内部扩容机制对于我们编写的代码十分有益。

1. 介绍

ArrayListjava.util包下的一个类,它实现了动态数组的数据结构。相比于传统数组,ArrayList具有自动扩容的特性,可以根据需要动态地调整数组的大小。

2. 扩容机制

ArrayList的元素数量接近或超过其当前容量时,就会触发扩容操作。ArrayList的扩容机制主要涉及以下几个关键参数:

  • elementData: 用于存储实际元素的数组。
  • size: 当前ArrayList中元素的个数。
  • DEFAULT_CAPACITY: 默认初始容量,一般为10。
  • MAX_ARRAY_SIZE: 数组的最大容量,一般为Integer.MAX_VALUE - 8

2.1 扩容触发条件

扩容会在以下两种情况下触发:

  1. 添加元素时,size超过elementData的长度

  2. 使用带有指定初始容量的构造方法,并且该初始容量大于默认容量,也会触发扩容。

2.2 扩容操作过程

扩容的核心方法是 grow(int minCapacity)。下面是扩容的大致过程:

  1. 计算新容量:
    新容量一般为原容量的 1.5 倍,即 oldCapacity + (oldCapacity >> 1)。如果这个值仍然不足以容纳 minCapacity 个元素,那么新容量将被设置为 minCapacity

  2. 检查是否超过最大容量:

    如果新容量超过了 MAX_ARRAY_SIZE,则新容量将被设置为 Integer.MAX_VALUE。这是由于数组的最大长度是 Integer.MAX_VALUE

  3. 创建新数组并复制元素:

    利用 Arrays.copyOf 创建一个新的数组,并将原数组中的元素复制到新数组中。

  4. 替换原数组:

    elementData 指向新的数组。

2.3 扩容示例代码

以下是 ArrayList 扩容机制的示例代码:

private void grow(int minCapacity) {
    // 获取原容量
    int oldCapacity = elementData.length;
    // 计算新容量
    int newCapacity = oldCapacity + (oldCapacity >> 1);

    // 检查是否足够容纳minCapacity个元素
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;

    // 检查是否超过最大容量
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);

    // 创建新数组并复制元素
    elementData = Arrays.copyOf(elementData, newCapacity);
}

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // 溢出
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}

总结

了解ArrayList的扩容机制是编写高性能Java代码的重要一环。通过深入了解其内部实现,我们能够更好地利用这一数据结构,避免不必要的扩容操作,提高程序的效率。

希望通过本文的介绍,大家能够对ArrayList的扩容机制有一个清晰而深入的理解~

好了,以上就是本文的全部内容,如有问题欢迎留言讨论。

我是chowley,一个专注互联网技术和软件质量保障领域的博主,我们下次再见!

欢迎点赞、评论、收藏,it's important for me.

欢迎点赞、评论、收藏,it's important for me.

欢迎点赞、评论、收藏,it's important for me.