incava.org

This test compares the performance of these alternatives:

List list = new ArrayList();
// ... populate list with n Strings

(String[])list.toArray(new String[0]); // not preallocated
(String[])list.toArray(new String[n]); // preallocated for n

As might be expected, in general there is a time advantage to the preallocated approach:

list    iters   alloc   time

100     1000    n       10
100     1000    0       7
                diff:   -3

100     10000   n       28
100     10000   0       36
                diff:   8

100     100000  n       258
100     100000  0       346
                diff:   88

1000    1000    n       23
1000    1000    0       25
                diff:   2

1000    10000   n       321
1000    10000   0       582
                diff:   261

1000    100000  n       2408
1000    100000  0       2527
                diff:   119

10000   1000    n       261
10000   1000    0       265
                diff:   4

10000   10000   n       2660
10000   10000   0       2678
                diff:   18

10000   100000  n       25764
10000   100000  0       27348
                diff:   1584

100000  1000    n       3475
100000  1000    0       3445
                diff:   -30

100000  10000   n       33901
100000  10000   0       34190
                diff:   289

100000  100000  n       353836
100000  100000  0       341116
                diff:   -12720

Given that, except where performance really matters, I still prefer the non-preallocated (zero length) approach, due to its brevity, since real-world code is often more like this:

list.toArray(new HideouslyLongClassName[insipidlyLongCollectionName.size()]);

The test:

import java.util.*;

public class ToArrayTest
{
    public static void runTest(int listSize, int iterations)
    {
        boolean[] allocs = new boolean[] { true, false };

        long[] durations = new long[allocs.length];
        
        for (int ai = 0; ai < allocs.length; ++ai) {
            boolean alloc = allocs[ai];

            List list  = new ArrayList();
            for (int i = 0; i < listSize; ++i) {
                list.add("str" + i);
            }

            int toArraySize = alloc ? listSize : 0;
        
            long start = System.currentTimeMillis();
            for (int i = 0; i < iterations; ++i) {
                list.toArray(new String[toArraySize]);
            }

            long end      = System.currentTimeMillis();
            durations[ai] = end - start;

            System.out.println("" + listSize + "\t" + iterations + "\t" + 
                               (alloc ? "n" : "0") + "\t" + durations[ai]);
        }

        System.out.println("\t\tdiff:\t" + (durations[1] - durations[0]));
    }

    public static void main(String[] args)
    {
        int[] listSizes  = new int[] { 100, 1000, 10000, 100000 };
        int[] iterations = new int[] { 1000, 10000, 100000 };

        System.out.println("list\titers\talloc\ttime");
        System.out.println();

        for (int li = 0; li < listSizes.length; ++li) {
            for (int ii = 0; ii < iterations.length; ++ii) {
                runTest(listSizes[li], iterations[ii]);
                System.out.println();
            }
        }
    }

}

Valid HTML 4.01!

Valid CSS!