专业编程基础技术教程

网站首页 > 基础教程 正文

Java的ArrayList 扩容机制? arraylist扩容问题

ccvgpt 2024-10-12 14:03:56 基础教程 10 ℃

在 Java 集合框架中,ArrayList 是使用最广泛的集合之一。它是基于数组实现的动态数组,具有自动扩容的功能。扩容机制是 ArrayList 的一个重要特性,它让 ArrayList 能够应对动态变化的元素数量。接下来,我们将详细解读 ArrayList 的扩容机制,并结合源码进行说明。

Java的ArrayList 扩容机制? arraylist扩容问题


源码解析


我们从 ArrayList 的构造函数和 add 方法入手,逐步揭示其扩容机制。


构造函数


ArrayList 有多个构造函数,其中最常用的是无参构造函数和带初始容量的构造函数。


java


// 无参构造函数
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);
    }
}



无参构造函数会将 elementData 初始化为一个默认空数组 DEFAULTCAPACITY_EMPTY_ELEMENTDATA。而带初始容量的构造函数则根据提供的容量大小初始化数组。


add 方法


当我们向 ArrayList 中添加元素时,add 方法会检查是否需要扩容:


java


public boolean add(E e) {
    ensureCapacityInternal(size + 1); // 核心方法,确保容量
    elementData[size++] = e;
    return true;
}



ensureCapacityInternal 方法是扩容机制的核心:


java


private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

private void ensureExplicitCapacity(int minCapacity) {
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}



当 minCapacity 超过当前数组长度时,会调用 grow 方法进行扩容。


grow 方法


grow 方法是扩容的关键部分:


java


private static final int DEFAULT_CAPACITY = 10;

private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容 1.5 倍
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
}



扩容的策略是将容量增加到原来的 1.5 倍 (oldCapacity + (oldCapacity >> 1)),同时确保新容量不小于 minCapacity。如果新容量超过了最大数组大小 MAX_ARRAY_SIZE,则调用 hugeCapacity 方法进行特殊处理。


扩容机制设计的目的


扩容机制的设计目的是为了在动态添加元素时,避免频繁的内存分配和数据复制。通过按需扩容,ArrayList 能够高效地管理内存,同时保持灵活性。


性能对比


我们可以通过以下代码示例来对比扩容机制的性能:


java


import java.util.ArrayList;

public class ArrayListPerfTest {
    public static void main(String[] args) {
        // 预先指定容量的 ArrayList
        long startTime = System.nanoTime();
        ArrayList<Integer> listWithCapacity = new ArrayList<>(1000000);
        for (int i = 0; i < 1000000; i++) {
            listWithCapacity.add(i);
        }
        long endTime = System.nanoTime();
        System.out.println("ArrayList with initial capacity: " + (endTime - startTime) + " ns");

        // 默认构造函数的 ArrayList
        startTime = System.nanoTime();
        ArrayList<Integer> listWithoutCapacity = new ArrayList<>();
        for (int i = 0; i < 1000000; i++) {
            listWithoutCapacity.add(i);
        }
        endTime = System.nanoTime();
        System.out.println("ArrayList without initial capacity: " + (endTime - startTime) + " ns");
    }
}



运行上述代码可以发现,预先指定容量的 ArrayList 性能更好,因为它避免了多次扩容操作。


实际应用场景


  1. 动态数据集合:在需要频繁添加元素的场景中,ArrayList 的扩容机制可以保证集合的动态性和灵活性。
  2. 大数据处理:在处理大数据集时,预先指定容量可以提高性能,减少扩容带来的开销。

?

Tags:

最近发表
标签列表