我很好奇Java的类和double的原始类型之间的性能差异。所以我创建了一个小基准测试,发现类类型比基本类型慢3x-7x。 (在本地机器OSX上为3倍,在ideone上为7倍)
以下是测试:
class Main {
public static void main(String args[]) {
long bigDTime, littleDTime;
{
long start = System.nanoTime();
Double d = 0.0;
for (Double i = 0.0; i < 1432143.341; i += 0.1) {
d += i;
}
long end = System.nanoTime();
bigDTime = end - start;
System.out.println(bigDTime);
}
{
long start = System.nanoTime();
double d = 0.0;
for (double i = 0.0; i < 1432143.341; i += 0.1) {
d += i;
}
long end = System.nanoTime();
littleDTime = end - start;
System.out.println(littleDTime);
}
System.out.println("D/d = " + (bigDTime / littleDTime));
}
}
那么为什么Double类型这么慢?为什么它甚至实现了允许数学运算符?
答案 0 :(得分:21)
那么为什么Double类型这么慢?
因为该值包含在需要分配,释放,内存管理以及getter和setter的对象中
为什么甚至实现允许数学运算符?
因为autobox意味着允许你使用这样的包装器而不用担心它们不是普通的值。您希望无法拥有ArrayList<Double>
吗?性能并不总是必要,并且根据情况可以接受3x-7x的性能下降。优化是一项并非始终存在的要求。
在任何情况下都是如此,使用LinkedList
随机访问元素可能过度,但这并不意味着LinkedList
根本不应该实现。这并不意味着使用链接列表进行少量随机访问可能会对性能造成太大影响。
最后一点:在对这些事情进行基准测试之前,你应该让VM热身。
答案 1 :(得分:8)
您通常不会使用Double
,Integer
等。(偶尔Integer
等可能有助于存储“可选”值 - 您可能希望它为{ {1}}有时null
这种情况不太可能,因为Double
适用于那些人。{/ p>
NaN
存在的原因如下。 Java有两种主要类型的值:对象(基本上类似于没有算术的C / C ++指针)和原始值(例如Double
)。像double
这样的类可以定义为接受任何ArrayList
,允许用户将Object
,String
或他们喜欢的任何内容存储在一个中 - 但是原始值如File
这个定义没有涵盖。所以像double
这样的类可以让像Double
这样的类更容易存储ArrayList
,而不需要double
的作者为所有基本类型创建特殊版本。
答案 2 :(得分:4)
Double
是一个装箱double
。因此,一般而言,编译后的代码必须在对Double
执行任何操作之前检查Double
。这当然比什么都不做要慢。
Object
(以及原语的其他盒装版本)很有用,因为它是Object
。这允许您将其传递给需要Double
的函数,并将其转发回其他地方的double
。更有用的是,它允许泛型类型包含它:泛型类型不能包含Double
或任何其他原语,但它可以包含{{1}}。