17

我很好奇 Java 的类和 double 的原始类型之间的性能差异是什么。所以我创建了一个小基准,发现类类型比原始类型慢 3 到 7 倍。(本地机器 OSX 上 3x,ideone 上 7x)

这是测试:

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 类型会慢很多呢?为什么它甚至被实现为允许数学运算符?

4

3 回答 3

22

那么为什么 Double 类型会慢很多呢?

因为值被包装在一个需要分配、释放、内存管理以及 getter 和 setter 的对象中

为什么它甚至被实现为允许数学运算符?

因为 autobox 旨在允许您使用此类包装器,而不必担心它们不是普通值这一事实。你宁愿不能拥有一个ArrayList<Double>吗?性能并不总是必要的,根据情况将性能降低 3 到 7 倍是可以接受的。优化是一项并不总是存在的要求。

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

最后一点:在对此类事物进行基准测试之前,您应该让 VM 预热。

于 2013-03-23T03:21:04.047 回答
8

您通常不会使用Double,Integer等。(有时Integeretc. 可用于存储“可选”值 - 您null有时可能希望使用它。这是不太可能的,Double因为NaN它们可用。)

存在的理由Double如下。Java 有两种主要的值类型:对象(本质上就像没有算术的 C/C++ 指针)和原始值(例如double)。类 likeArrayList可以定义为接受 any Object,这允许用户存储StringFile或他们喜欢的任何东西 - 但原始值 likedouble不在这样的定义中。所以像这样的类的存在是为了让像存储sDouble这样的类更容易,而不需要作者为所有原始类型创建特殊版本。ArrayListdoubleArrayList

于 2013-03-23T03:26:19.080 回答
4

Double是盒装的double。因此,通常编译后的代码必须Double在对其进行任何操作之前检查是否为 null。这当然比什么都不做要慢。

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

于 2013-03-23T03:26:00.130 回答