为什么要使用ArrayList(int capacity)呢?

时间:2012-03-20 03:44:44

标签: java arraylist benchmarking

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

是否有任何全面的基准测试比较将初始添加元素添加到ArrayList所需的时间与预先设置ArrayList的容量相比?

3 个答案:

答案 0 :(得分:6)

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

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

答案 1 :(得分:3)

我没有任何实质性的内容可以添加到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

答案 2 :(得分:1)

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