【问题标题】:Why bother using ArrayList(int capacity)?为什么要使用 ArrayList(int capacity)?
【发布时间】:2012-03-20 03:44:43
【问题描述】:

所以几乎每个与 ArrayList 中容量相关的问题都是如何使用它或(奇怪地)访问它,我对这些信息非常熟悉。如果您碰巧知道或大致了解 ArrayList 中有多少项目,我感兴趣的是是否真的值得使用设置容量的 ArrayList 构造函数?

是否有任何全面的基准来比较将元素简单地添加到 ArrayList 与预先设置 ArrayList 的容量需要多长时间?

【问题讨论】:

  • 当 ArrayList 的容量达到时,CLR 会创建一个新的 ArrayList,其容量是原数组的两倍,并将原数组中的所有元素复制到新创建的数组中。因此,如果您对所需的大小有一些想法,可以通过预设 ArrayList 的大小来节省这些额外的工作。
  • @Deepansh:这不是 Java 问题吗? CLR 是如何出现的?我猜你的意思是JVM?此外,您的描述似乎是正确的,但“在 CLR”(.Net)中,我预先分配大小需要更多时间。至少,当我在 1000000 个项目上测试它时会发生这种情况。我测试了 10-15 次,每次默认的 ArrayList 构造函数都赢了!
  • 我说的是 ArrayList,但它可以应用于一般概念,即拥有由数组内部支持的集合的列表视图。
  • 对不起 Anthony,因为 ArrayList 也存在于 .net 中,所以我忽略了 java 标签。但我认为 .net 和 java 中的概念是相同的。
  • @DeepanshGupta 'The details of the growth policy are not specified' for ArrayList 但实际上 JDK 使用的增长因子是 1.5,而不是 2。

标签: java arraylist benchmarking


【解决方案1】:

显然,对于任何特定的应用程序,您都必须测试任何性能调整以确定它们是否真的是优化(以及它们是否真的必要),但有时明确设置容量是值得的。例如:

  • 您正在创建大量的数组列表,其中大部分都非常小。在这种情况下,您可能希望将初始容量设置得非常低,和/或在完成填充给定数组时修剪容量。 (在这种情况下,优化与其说是速度问题,不如说是内存使用问题。但请注意,列表本身有内存开销,它包含的数组也是如此,所以在这种情况下,重新设计可能会更好一种减少列表的方法。)
  • 您正在创建一个已知大小 非常 大的数组列表,并且您希望添加 每个 元素的时间非常小(可能是因为每次您添加一个元素,您必须向外部数据源发送一些响应)。 (默认的几何增长需要摊销恒定时间:每隔一段时间,就会产生巨大的损失,因此整体平均性能完全没问题,但如果您关心单独进行的单个插入,那可能还不够好。)

【讨论】:

    【解决方案2】:

    我对 ruakh 的回答没有什么实质性的补充,但这里有一个快速测试功能。我保留了一个废弃项目来编写这样的小测试。将 sourceSize 调整为代表您的数据的东西,您可以大致了解效果的大小。如图所示,我看到它们之间的因子约为 2。

    import java.util.ArrayList;
    import java.util.Random;
    
    public class ALTest {
        public static long fill(ArrayList<Byte> al, byte[] source) {
            long start = System.currentTimeMillis();
            for (byte b : source) {
                al.add(b);
            }
            return System.currentTimeMillis()-start;
        }
        public static void main(String[] args) {
            int sourceSize = 1<<20; // 1 MB
            int smallIter = 50;
            int bigIter = 4;
    
            Random r = new Random();
            byte[] source = new byte[sourceSize];
            for (int i = 0;i<bigIter;i++) {
                r.nextBytes(source);
                {
                    long time = 0;
                    for (int j = 0;j<smallIter;j++) {
                        ArrayList<Byte> al = new ArrayList<Byte>(sourceSize);
                        time += fill(al,source);
                    }
                    System.out.print("With: "+time+"ms\t");
                }
                {
                    long time = 0;
                    for (int j = 0;j<smallIter;j++) {
                        ArrayList<Byte> al = new ArrayList<Byte>();
                        time += fill(al,source);
                    }
                    System.out.print("Without: "+time+"ms\t");
                }
                {
                    long time = 0;
                    for (int j = 0;j<smallIter;j++) {
                        ArrayList<Byte> al = new ArrayList<Byte>();
                        time += fill(al,source);
                    }
                    System.out.print("Without: "+time+"ms\t");
                }
                {
                    long time = 0;
                    for (int j = 0;j<smallIter;j++) {
                        ArrayList<Byte> al = new ArrayList<Byte>(sourceSize);
                        time += fill(al,source);
                    }
                    System.out.print("With: "+time+"ms");
                }
                System.out.println();
            }
        }
    }
    

    输出:

    With: 401ms Without: 799ms  Without: 731ms  With: 347ms
    With: 358ms Without: 744ms  Without: 749ms  With: 342ms
    With: 348ms Without: 719ms  Without: 739ms  With: 347ms
    With: 339ms Without: 734ms  Without: 774ms  With: 358ms
    

    【讨论】:

      【解决方案3】:

      ArrayList internals 使用简单的数组来存储其元素,如果元素的数量超过底层数组的容量,则需要调整大小。因此,如果您知道 List 将包含多少项,您可以通知 ArrayList 使用所需大小的数组,这样就不需要或执行调整大小的逻辑。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-01
        • 2016-08-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多