【问题标题】:When an ArrayList resizes itself, how many elements does it add?当 ArrayList 调整自身大小时,它添加了多少元素?
【发布时间】:2011-02-01 15:17:47
【问题描述】:

Java 的 ArrayList 会在需要时动态扩展自身。扩展发生时它添加了多少元素?

它是将旧数组复制到新数组中,还是以某种方式将两者联系在一起?

【问题讨论】:

    标签: java arraylist


    【解决方案1】:

    看看source code

    int newCapacity = (oldCapacity * 3)/2 + 1;
    

    具体的因子因实现而异,gnu 使用因子 2。没关系,只是用内存换速度。

    它将所有元素复制到一个新数组中。

    【讨论】:

    • 适用于 Sun JDK,但未指定。
    • 谢谢,实际上它因实现而异。
    【解决方案2】:

    它创建一个新的 double 数组,该数组是大小的倍数,并将元素复制过来。 (我不确定实际乘数是否根据 Java 标准指定。)

    现在很自然的问题是,为什么?为什么不每次都添加五个元素?

    这是为了让事情变得更快:您免费添加 n 元素,并且在元素 n + 1 上,您必须复制 n 将前面的元素放入大小为 2n 的数组中。因此,复制这些 n 元素的成本会分散(“摊销”)到它们自身上(因为您之前免费添加了它们),所以平均而言,添加每个元素的成本是 n /n,或者每个元素大约 1 次操作。

    (有关此主题的更多讨论,请参阅this link。)

    【讨论】:

    • 错了!至少对于 Sun 的 ArrayList,大小不会翻倍。
    • 摊销很好的解释。
    【解决方案3】:

    严格来说,确切的调整大小行为是not specified in the spec/JavaDoc

    除了添加一个元素具有恒定的摊销时间成本这一事实之外,没有指定增长策略的细节。

    这意味着内部数组不能通过添加一个常数来调整大小,但必须涉及一些乘法。正如 maartinus 所指出的,Sun JDK 和 OpenJDK 将大小乘以 1.5(大约)。

    【讨论】:

    • 你知道为什么吗?我很好奇为什么他们默认不加倍。
    • Mehrdad 解释了它成倍增加的原因。确切的因素是内存效率和避免多个副本之间的决定。使用因子 2 可能会浪费太多内存(最多 50% 的数组可能未被使用!)。使用更接近 1 的因子(例如 1.1)意味着需要更频繁地复制数组。
    猜你喜欢
    • 2013-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-26
    • 2014-04-03
    • 2011-09-08
    • 1970-01-01
    相关资源
    最近更新 更多