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

时间:2013-11-05 05:15:21

标签: java arrays

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

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

所以,我试图理解一个数组的系统规范,使其不可复制。

4 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分:4)

阵列是一个连续的内存块。根据您初始化的内容,它可能相对较小,或相对较大。

比方说,我有一个包含十个元素的数组。

int[] arr = new int[10];

JVM的底层实现现在必须要求操作系统将40个连续字节分配给程序。操作系统有义务,现在您有40个字节,您可以使用熟悉的名称arr

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

假设我们认为10太短了。我们需要把它做大 - 增加十倍。

int arr2 = new int[100];

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

调整数组大小不仅仅是在几个内存位置上移动引用 - 它是关于查找连续内存的新块来存储数据。


你提到ArrayList - 它的好奇之处在于它由一个“自动”调整大小的数组支持。嗯,有一个关于调整大小操作的问题 - 它很昂贵。

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

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

基本上,每次需要调整大小时,它会分配相当于原始后备阵列1.5倍的空间。如果ArrayList非常大,这会非常快地获得昂贵 - 系统必须走出去并找到越来越多的连续内存来分配,这意味着JVM必须找到更多连续的空间,意味着更多的时间花在垃圾收集上,最终意味着更少的性能。

以上内容甚至没有覆盖重新复制数据。

答案 2 :(得分:3)

假设您定义了一个16字节的数组,一个整数&amp;另一个整数。

现在你希望调整它的大小......

======================================================
|| || || || || || || || || || || || || || || || || ||   --->  (Memory)
======================================================
\________________/\____/\____/  
 ----------------  ----  ----
      Array(16)     Int  Int

上面的数组是否容易调整大小?

新的数组必须分配给下一个可用的空闲内存块,因为程序已经为整数保留了块。

答案 3 :(得分:2)

要解决此问题,矢量就在那里。

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