2013-03-23 101 views
12

我很好奇Java类和原始类型之间的性能差异。所以我创建了一个基准,发现类的类型比原始类型慢3倍-7倍。 (在本地机器上OSX,7倍3倍的ideone)Java双倍与双倍:类型与原始类型

下面是测试:

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)); 
    } 
} 

http://ideone.com/fDizDu

那么,为什么是Double类型这么多慢?为什么它甚至被实现以允许数学运算符?

+1

由于需要装箱和取消装箱,速度很慢。这是预期的行为。 – 2013-03-23 03:16:46

+0

@HovercraftFullOfEels这是有道理的,但它仍然看起来像很多开销。 – 2013-03-23 03:19:31

+1

这是一个很大的开销。因此,您应该避免在时间关键的代码中使用原始包装类型。 – 2013-03-23 03:20:16

回答

17

那么为什么Double类型慢得多?

因为价值被包裹其中需要分配,回收,内存管理以及getter和setter对象内

为什么即使实现,让数学运算符?

因为autobox是为了让您使用这样的包装而不用担心它们不是普通的值。你想不能有ArrayList<Double>?性能为并非总是需要,根据情况可能可以接受3至7倍性能下降。优化是一个并不总是存在的要求。

在任何情况下都是如此,使用随机访问元素的LinkedList可能会矫枉过正,但这并不意味着根本不应该实现LinkedList。这也不意味着对少量随机访问使用链表会严重干扰性能。

最后一点说明:在基准测试之前,应让虚拟机热身。

3

Double是盒装的double。因此,一般来说编译代码必须先检查Double为null,然后再做任何事情。这当然比无所事事慢。

Double(和其他原始版本的盒装版本)很有用,因为它是Object。这使您可以将它传递给需要Object的函数,并将其转换回Double其他地方。更有用的是,它允许泛型类型包含它:泛型类型不能包含double或任何其他基元,但它可以包含Double

8

你通常不会使用DoubleInteger等(偶尔Integer等等都可以存储在“可选”值很有用 - 你可能希望它是null有时这是因为DoubleNaN可能性较小)

原因Double存在如下。 Java有两种主要类型的值:对象(本质上类似于没有算术的C/C++指针)和原始值(例如double)。类似ArrayList可以定义为接受任何Object,它允许用户将String,File或其他任何他们喜欢的东西存储在一个中 - 但像double这样的原始值不包含在此定义中。因此存在像Double这样的类可以使像ArrayList这样的类更容易地存储double,而不需要ArrayList的作者为所有基元类型创建特殊版本。