为什么Integer to int to Integer比Integer快10倍?

时间:2013-03-23 12:36:01

标签: java boxing

我有两个相同大小的数组和两个方法。

public class Client {
    private static int[] ints;
    private static final int COUNT = 10000000;
    private static Integer[] integers;

    public static void main(String[] args) {
        Random rand = new Random();
        integers = new Integer[COUNT];
        for (int i = 0; i < integers.length; i++) {
            integers[i] = rand.nextInt();
        }

        ints = new int[COUNT];
        for (int i = 0; i < ints.length; i++) {
            ints[i] = rand.nextInt();
        }

        primitiveToObject();
        objectsToPrimitiveToObject();
    }

    public static  void primitiveToObject() {
        long start = new Date().getTime();
        List<Integer> objects = new ArrayList<>(ints.length);
        for (int i = 0; i < ints.length; i++) {
            int value = ints[i] + 1;
            objects.add(value);          //Boxing
        }
        System.out.println("prim -> object = " + (new Date().getTime() - start));
    }

    public static void objectsToPrimitiveToObject() {
        long start = new Date().getTime();
        List<Integer> result= new ArrayList<>(integers.length);
        for (int i = 0; i < integers.length; i++) {
            int value = integers[i] + 1; //Unboxing
            result.add(value);           //Boxing
        }
        System.out.println("obj -> prim -> object = " + (new Date().getTime() - start));
    }
}

为什么objectsToPrimitiveToObject()装箱和拆箱的速度比没有拆箱的primitiveToObject()快10倍?

1 个答案:

答案 0 :(得分:3)

我认为这是一个关于如何对代码进行基准测试的人工制品。

我使用JVM 1.7.0_09-XX:+AggressiveOpts -XX:CompileThreshold=1

运行以下基准测试
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Main {
    static final int COUNT = 1000000;
    static int[] ints = new int[COUNT];
    static Integer[] integers = new Integer[COUNT];

    static void primitiveToObject() {
        List<Integer> objects = new ArrayList<Integer>(ints.length);
        for (int i = 0; i < ints.length; i++) {
            int value = ints[i] + 1;
            objects.add(value);                    //boxing
        }
    }

    static void objectsToPrimitiveToObject() {
        List<Integer> result= new ArrayList<Integer>(integers.length);
        for (int i = 0; i < integers.length; i++) {
            int value = integers[i] + 1;           //unboxing
            result.add(value);                     //boxing
        }
    }

    public static void main(String[] args) {
        Random rand = new Random();
        for (int i = 0; i < COUNT; ++i) {
            int val = rand.nextInt();
            ints[i] = val;
            integers[i] = val;
        }
        for (int i = 0; i < 10; ++i) {
            long start_p = System.currentTimeMillis();
            for (int j = 0; j < 100; ++j) {
                primitiveToObject();
            }
            long end_p = System.currentTimeMillis();
            long start_o = System.currentTimeMillis();
            for (int j = 0; j < 100; ++j) {
                objectsToPrimitiveToObject();
            }
            long end_o = System.currentTimeMillis();
            System.out.printf("p2o:%d o2p2o:%d\n", end_p - start_p, end_o - start_o);
        }
    }
}

结果如下:

p2o:2043 o2p2o:818
p2o:709 o2p2o:748
p2o:670 o2p2o:756
p2o:675 o2p2o:742
p2o:679 o2p2o:750
p2o:700 o2p2o:757
p2o:738 o2p2o:733
p2o:706 o2p2o:786
p2o:684 o2p2o:752
p2o:676 o2p2o:799

正如您所看到的,在最初的热身之后,primitiveToObject()更快,正如人们可能期望从一种方法做得更少的工作。

为了完整性,我还使用JDK 6对其进行了测试,并观察到了类似的结果。