为什么不能调整数组的大小?

use*_*127 10 java arrays

数组(原始数据或其他数据)无法动态调整大小的原因是什么?

我知道你可以使用ArrayList,但它背后的实现仍然是一个初始大小的数组(我认为它默认为50),当它超过50时,将创建一个新数组来包含这些元素.

所以,我试图理解一个数组的系统规范,使其不可调整.

Nat*_*nes 6

这是一个有效的问题,答案与计算机实际工作方式有关.

int[] array = new int[5]例如,在创建数组时,计算机会在内存中保留五个连续的空格,以便包含在该数组中的数据.但是,之后的内存空间可以立即用于存储其他信息.如果稍后要调整数组的大小,则必须将其他信息移动到其他位置以使数组变大.这是我们不想处理的大量改组,因此计算机架构师不允许使用数组调整大小来简化操作.


Mak*_*oto 5

数组本质上是一块连续的内存块。根据您将其初始化的内容,它可以相对较小,也可以相对较大。

举例来说,我有一个包含十个元素的数组。

int[] arr = new int[10];
Run Code Online (Sandbox Code Playgroud)

JVM 的底层实现现在必须向操作系统请求 40 个连续字节分配给程序。操作系统强制要求,现在您有 40 个字节,您可以通过熟悉的名称使用它们arr

请注意,该数组可能在其两侧共享空间 - 它附近还有其他引用或信息位,并且它不能只是走到其自身的第十一个位置并“声明”它。

假设我们认为 10 太短了。我们需要将其放大十倍。

int arr2 = new int[100];
Run Code Online (Sandbox Code Playgroud)

现在,操作系统必须在内存中找到彼此相邻的 400 字节空间,考虑到对象的生命周期、垃圾收集的运行时间等,这可能很重要,也可能很重要。

调整数组大小并不是简单地将引用移动到几个内存位置 - 而是寻找新的连续内存块来存储数据。


你提到ArrayList-它很奇怪,因为它由一个“自动”调整大小的数组支持。好吧,调整大小操作有一个问题——成本高昂。

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

ensureCapacityInternal做了一些有趣的事情...最终调用ensureExplicitCapacity...最终调用grow

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);
}
Run Code Online (Sandbox Code Playgroud)

本质上,每次需要调整大小时,它都会分配等于原始后备数组 1.5 倍的空间。如果内存相当大,这很快就会变得昂贵ArrayList- 系统必须出去寻找越来越多的连续内存来分配,这意味着 JVM 必须找到更多的连续空间,这意味着花费更多的时间进行垃圾收集,最终意味着更少的时间表现。

以上甚至没有涉及将数据复制回来。


pa1*_*pal 2

为了解决这个问题,就有了向量。

您应该使用向量就像动态分配内存一样。