当前位置: 首页 > 面试题库 >

在Java 8中,为什么ArrayList的默认容量现在为零?

岳英锐
2023-03-14
问题内容

我记得在Java 8之前,默认容量ArrayList是10。

令人惊讶的是,对默认(void)构造函数的评论仍然是: Constructs an empty list with an initial capacity of ten.

来自ArrayList.java

/**
 * Shared empty array instance used for default sized empty instances. We
 * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
 * first element is added.
 */
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

...

/**
 * Constructs an empty list with an initial capacity of ten.
 */
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

问题答案:

从技术上讲,10如果您允许对备用数组进行延迟初始化,则它为,而不是零。看到:

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

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}

哪里

/**
 * Default initial capacity.
 */
private static final int DEFAULT_CAPACITY = 10;

您所指的只是在所有最初为空的ArrayList对象之间共享的大小为零的初始数组对象。即 懒惰地10保证的容量,Java 7中也存在这种优化。
__

诚然,建设者合同并不完全准确。也许这是造成混乱的根源。

背景

这是Mike Duigou的电子邮件

我已经发布了空ArrayList和HashMap补丁的更新版本。

http://cr.openjdk.java.net/~mduigou/JDK-7143928/1/webrev/

修订后的实现 没有 为这两个类引入 任何新字段
。对于ArrayList,仅当列表以默认大小创建时才进行后备阵列的延迟分配。根据我们的性能分析团队的说法,大约有85%的ArrayList实例是在默认大小下创建的,因此此优化将在绝大多数情况下有效。

对于HashMap,创意使用阈值字段来跟踪请求的初始大小,直到需要存储桶数组为止。在读取方面,使用isEmpty()测试空映射案例。在写入大小上,比较(table
== EMPTY_TABLE)用于检测是否需要对存储桶数组进行充气。在readObject中,还有更多工作来尝试选择有效的初始容量。

来自: http : //mail.openjdk.java.net/pipermail/core-libs-
dev/2013-April/015585.html



 类似资料:
  • 问题内容: 我看到了ArrayList的Java文档,发现ArrayList的初始容量为10。 我认为这是2的幂是有道理的,但为什么是10? 我还检查了HashMap的初始容量,这是16,这很有意义。 数字10后面是否有具体原因? 问题答案: 这是简单的增长数组。当尝试添加元素并且超出缓冲区大小时,它只是在增长。因此,初始大小可以是任何正值。 1将太少。即使有一些元素,我们也会有一些调整大小的操作

  • 问题内容: 为什么下面的代码抛出ConcurrentModificationException?JoshBloch可以避免ConcurrentModificationException。 问题答案: 使用“ for each”循环时,不能在列表上使用remove。相反,您可以使用此方法在迭代器上调用remove: 如果您实际上想用“ 200”代替每个值,或用其他值代替,则建立一个新列表可能更有意义

  • 本文向大家介绍接口变量在Java中默认为静态且为最终变量,为什么?,包括了接口变量在Java中默认为静态且为最终变量,为什么?的使用技巧和注意事项,需要的朋友参考一下 接口定义行为的协议,而不是行为的协议。实现接口的类遵守该接口定义的协议。 接口变量是静态的,因为无法单独实例化Java接口。必须在没有实例的静态上下文中分配变量的值。 final修饰符确保分配给接口变量的值是无法重新分配的真实常量。

  • 问题内容: 为什么在类中声明的变量具有默认值,但是在方法内部声明的变量(称为“局部变量”)在Java中没有默认值? 例如 在上面的示例中,变量的默认值为0,但是变量给出了可能尚未初始化的错误。 问题答案: 所有成员变量都必须加载到堆中,因此在创建类的实例时必须使用默认值进行初始化。对于局部变量,它们不会被加载到堆中,直到在Java7之前被使用,它们才会存储在堆栈中,因此我们需要显式初始化它们。现在

  • Java中的本质上是不可靠的。具体地说,我对接口的最大问题是,它需要一个不定义方法本身的方法行为。因此,如果遍历一个列表,您必须使用反射来访问它定义的行为。然而,在Java8中,我们现在有了默认方法,现在我问为什么在中没有默认的方法。 我理解为什么接口不能默认对象方法,但是,这是一个明确的设计决定,所以可以做出例外。 我有点想弃用并将其内部代码更改为类似以下内容: 然后继续使用使作为中的默认方法的

  • 问题内容: 默认方法是Java工具箱中一个不错的新工具。但是,我试图编写一个定义方法版本的接口。Java告诉我,这是禁止的,因为in中声明的方法可能无法编辑。为什么会这样呢? 我知道有一个“基类始终获胜”规则,因此默认情况下(pun;),方法的任何实现都会被该方法覆盖。但是,我认为没有理由为什么规范中的方法不应有例外。特别是因为它具有默认实现可能非常有用。 那么,Java设计者决定不允许方法覆盖方