区分数组列表的容量和数组的大小

Kum*_*r V 15 java arrays arraylist

我在Core Java I书中阅读了下面的代码片段.

将数组列表分配为 新的ArrayList <'Employee>(100)//容量为100

新员工[100] //大小为100时分配新数组不同

数组列表的容量与数组的大小之间存在重要区别.如果您分配一个包含100个条目的数组,则该阵列有100个插槽,可供使用.容量为100个元素的数组列表有可能容纳100个元素(实际上,超过100个,以额外的重新分配为代价); 但是在开始时,即使在初始构造之后,数组列表也根本不包含任何元素.

当我看到源代码数组列表时,构造函数创建一个给定容量的Object数组,该数组已准备好容纳给定容量的元素(下面是代码片段).

public ArrayList(int initialCapacity) {
     super();
     if (initialCapacity < 0)
         throw new IllegalArgumentException("Illegal Capacity: "+
                                            initialCapacity);
     this.elementData = new Object[initialCapacity];
 }
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚作者在上面的文字中提到的实际差异.

Rea*_*tic 26

如果你分配一个新的数组arr = new Employee[100],那个array(arr.length)的大小将是100.它有100个元素.所有元素最初都为null(因为这是一个对象引用数组),但仍然有100个元素.

如果你做了类似的事情list = new ArrayList <Employee>(100),并尝试检查list.size(),你将得到0.列表中没有元素.

在内部,确实ArrayList在需要扩展其容量之前分配足够的地方放置100个项目,但这是一个内部实现细节,并且该列表将其内容呈现为"没有项目存储".只有你真的这样做list.add(something),你才会在列表中有项目.

因此,尽管列表预先分配存储,但与程序通信的API会告诉您其中没有项目.您无法使用其内部数组中的空项 - 您无法检索它们或更改它们.

  • 确实如此,但是ArrayList的用户无法使用这些元素.差异不在于分配的内存量.这是你可以或不可以使用数组列表与数组相关的事情. (5认同)
  • 但是线元素真正发生了什么= new Object [initialCapacity].是否创建了Object数组,其中所有元素都设置为null,因为它与正常的Object数组创建一样. (2认同)

小智 7

ArrayList只是表示抽象列表的一种方式,ArrayList的容量是系统如何实现逻辑列表的实现细节.

ArrayList通过使用"隐藏"下的实际数组来存储列表的元素.计算机存储器中阵列的实际实现在分配时具有一定的大小; 这个大小是ArrayList的容量.除了固定长度数组之外,ArrayList还通过存储列表的逻辑长度来模拟可变大小的列表.因此,如果您有一个容量为10且包含4个逻辑元素的ArrayList,则ArrayList可以表示为长度和数组

(4)| e1 | e2 | e3 | e4 | __ | __ | __ | __ | __ | __ |

其中(4)是列表的逻辑长度,'__'表示被忽略的数据,因为它不是逻辑列表的一部分.如果您尝试访问此ArrayList的第5个元素,它将抛出异常,因为它知道第五个元素尚未初始化.如果我们在列表中附加一个额外的元素e5,则ArrayList变为

(5)| e1 | e2 | e3 | e4 | e5 | __ | __ | __ | __ | __ |

请注意,容量没有改变,而逻辑长度有,因为底层数组仍然能够处理逻辑列表中的所有数据.

如果您设法向此列表添加十个以上的元素,则ArrayList不会中断.ArrayList是一个旨在与所有数组操作兼容的抽象.相反,ArrayList在其逻辑长度超过其原始容量时会更改其容量.如果我们要将元素(a1,a2,...,a7)添加到上面的列表中,结果ArrayList可能看起来像

(12)| e1 | e2 | e3 | e4 | e5 | a1 | a2 | a3 | a4 | a5 | a6 | a7 | __ | __ | __ | __ | __ | __ | __ | __ |

容量为20.

一旦创建了ArrayList,就可以忽略后面所有编程中的容量; 逻辑不受影响.但是,在某些操作下系统的性能会受到影响.例如,增加容量可能涉及分配更大的阵列,将第一个阵列复制到第二个阵列然后执行操作.与例如链表上的相同操作相比,这可能非常慢.因此,选择ArrayList的容量大于或至少可比较实际运行时环境中预期的实际元素数是明智的.