我对自动装箱和性能感到好奇,因为我在应用程序中进行了很多速度敏感的数学运算,因此我进行了一些测试...

public static void main(String[] args) {
    // Some initialization so I know it's not involved
    ArrayList<Integer> list = new ArrayList<Integer>();
    list.add(0);
    int[] regArray = new int[1];
    long total = 0;

    // This one uses an array and primitive type
    long start = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++) {
        regArray[0] = i + 10;
        if (regArray[0] % 1000 == 0) total += regArray[0];
    }
    System.out.println("Runtime in millis: " + (System.currentTimeMillis() - start));
    System.out.println(total);

    // This one autoboxes, but still uses the Object type because it's a list
    total = 0;
    start = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++) {
        list.set(0, i + 10);
        if (list.get(0) % 1000 == 0) total += list.get(0);
    }
    System.out.println("Runtime in millis: " + (System.currentTimeMillis() - start));
    System.out.println(total);

    // This one doesn't autobox
    total = 0;
    start = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++) {
        list.set(0, new Integer(i + 10));
        if (list.get(0).intValue() % 1000 == 0) total += list.get(0).intValue();
    }
    System.out.println("Runtime in millis: " + (System.currentTimeMillis() - start));
    System.out.println(total);
}

这是一个示例输出:
Runtime in millis: 78
50005000000
Runtime in millis: 250
50005000000
Runtime in millis: 250
50005000000

这似乎表明我应该在速度敏感的数学应用程序中远离List<>和子类。您是否同意,stackoverflow?

编辑:我的实际用例是,我需要存储数百个intfloat,它们会经常变化并且很大程度上无法预测(我说这主要是因为它们将保持在狭窄范围内,但是我不知道它们会做什么)在这个狭窄的范围内),我需要对这些数字进行数学运算时需要毫秒级的响应时间。

最佳答案

微基准测试很难!我重写了您的基准测试,以使用caliper:

import com.google.caliper.Runner;
import com.google.caliper.SimpleBenchmark;

import java.util.ArrayList;

public class ListsBenchmark extends SimpleBenchmark {

    private final ArrayList<Integer> list = new ArrayList<Integer>();
    int[] regArray = new int[1];
    long total;

    @Override
    protected void setUp() throws Exception {
        list.add(0);
        total = 0;
    }

    public long timeArrayAndPrimitiveType(int reps) {
        for (int i = 0; i < reps; i++) {
            regArray[0] = i + 10;
            if (regArray[0] % 1000 == 0)
                total += regArray[0];
        }
        return total;
    }

    public long timeListWithAutoboxing(int reps) {
        for (int i = 0; i < reps; i++) {
            list.set(0, i + 10);
            if (list.get(0) % 1000 == 0)
                total += list.get(0);
        }
        return total;
    }

    public long timeNoAutoboxing(int reps) {
        for (int i = 0; i < reps; i++) {
            list.set(0, new Integer(i + 10));
            if (list.get(0).intValue() % 1000 == 0)
                total += list.get(0).intValue();
        }
        return total;
    }

    public static void main(String[] args) {
        Runner.main(ListsBenchmark.class, new String[]{});
    }

}

我尚未修改您的原始代码。我发现的是:
  • 数组的速度约为
  • 的3倍
  • 创建新的Integer会稍微快一些(!),也许缓存需要一些价格,或者可能只是我的体系结构(带有4核和3 GiB内存笔记本电脑的32位Ubuntu)

  • 在图表上(可以自行运行!):

    10-02 22:40