Java中的自动装箱与手动装箱 [英] Autoboxing versus manual boxing in Java

查看:177
本文介绍了Java中的自动装箱与手动装箱的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么第二段代码更快?

Why is the second piece of code faster?

Map<Integer, Double> map = new HashMap<Integer, Double>();
for (int i = 0; i < 50000; i++) {
    for (double j = 0.0; j < 10000; j++) {
        map.put(i, j);
    }
}

Map<Integer, Double> map=new HashMap<Integer, Double>();
for (int i = 0; i < 50000; i++) {
    for (double j = 0.0; j < 10000; j++) {            
        map.put(new Integer(i), new Double(j));
    }
}

推荐答案

自动装箱使用Integer.valueOf,它在内部缓存Integer对象中的小整数(默认为-128到127,但是最大值可以使用"java .lang.Integer.IntegerCache.high"属性-请参阅Integer.valueOf的源代码,因此它与直接调用new Integer不同.因为Integer.valueOf在调用new Integer之前会快速检查整数值的大小,所以直接调用new Integer会快一些(尽管如果您有很多小整数,它会使用更多的内存). Java中的分配速度非常快,GC的时间与短寿命对象的数量成正比(即与垃圾的数量不成比例),因此GC也非常快.

Autoboxing uses Integer.valueOf, which internally caches Integer objects for small integers (by default -128 to 127, but the max value can be configured with the "java.lang.Integer.IntegerCache.high" property - see the source code of Integer.valueOf), so it is different from calling new Integer directly. Because Integer.valueOf does a quick check for the magnitude of the integer value before calling new Integer, it's a little bit faster to call new Integer directly (though it uses more memory if you have lots of small integers). Allocation in Java is very fast, and the time doing GC is proportional to the number of live short-lived objects (i.e. not proportional to the amount of garbage), so GC is also very fast.

但是取决于JVM版本和启用的优化,有标量替换优化,它在分配短期对象时会产生更大的性能差异(在您的示例中,无法完成优化,因为您正在将对象存储在地图中,但在许多其他情况下很有用).

But depending on the JVM version and which optimizations are enabled, there is the scalar replacement optimization, which can in produce a much bigger performance difference when allocating short-lived objects (in your example that optimization can't be done, because you are storing the objects in a map, but in many other situations it's useful).

在最新的JVM版本中,有标量替换优化(除了1.6.0_18中的转义分析被暂时禁用)之外,这意味着可以优化短期对象的分配.在JVM中进行标量替换时,有人做了基准测试,其中包含与您的代码相似的代码.结果是使用原语的代码最快,使用显式new Integer()调用的代码几乎与使用原语的代码一样快,而使用自动装箱的代码要慢得多.这是因为自动装箱使用Integer.valueOf,并且至少在那时,标量替换优化没有考虑到这种特殊情况.从那以后,我不知道优化是否有所改善.

In recent JVM versions there is scalar replacement optimization (except in 1.6.0_18 where escape analysis is temporarily disabled), which means that allocations of short-lived objects can be optimized away. When scalar replacement in JVM was new, somebody made a benchmark where there was code similar to yours. The result was that the code which used primitives was fastest, the code with explicit new Integer() calls was nearly as fast as the one using primitives, and the code which used autoboxing was much slower. This was because autoboxing uses Integer.valueOf and at least back then scalar replacement optimization did not take that special case into consideration. I don't know whether the optimization has been improved since then.

这篇关于Java中的自动装箱与手动装箱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆