【问题标题】:Most efficient way to multiply a boxed double by 2?将盒装双倍乘以 2 的最有效方法?
【发布时间】:2013-01-11 16:29:59
【问题描述】:

假设我们有一个装箱的 double 变量 foo,我们想将其值乘以 2 并将其存储在另一个装箱的 double 变量 bar 中。从以下几种方式,

方法一:

Double bar = foo * 2;

和,

方法二:

Double bar = Double.valueOf(foo.doubleValue() * 2);

考虑到效率、可读性等,哪一个更可取?还是这些方法的差异如此微不足道,以至于这些方法实际上是等效的?

【问题讨论】:

  • 从可读性来看,你可以自己回答问题,从效率来看,我认为这取决于 VM 的实现
  • 两者应该是等价的,因为自动装箱被编译成对valueOf的调用
  • @IanRoberts:虽然经常声称,但这实际上不是必需的。 JLS 仅指定将非 NaN 的原始 double p 转换为“类和 Double 类型的引用 r,使得 r.doubleValue() 计算为 p”。编译器也可以使用例如"new Double(p)" 而不是 "Double.valueOf(p)" 并且仍然遵守 JLS。
  • @jarnbjo 原则上是正确的,但 not in practice.
  • @IanRoberts:所以如果 mishadoff 的车是黑色的,那么所有的车都是黑色的?

标签: java double wrapper


【解决方案1】:

方法一更好。

  • 人类可以阅读
  • 在其他条件相同的情况下,字符越少越好
  • 编译器可能会消除任何性能差异。

【讨论】:

  • 非常同意第 1 点和第 3 点。这些可能是您在进行任何优化之前首先想到的事情。
【解决方案2】:

第一个。它具有更好的可读性,并将所有装箱/拆箱操作隐藏在幕后。

不要考虑乘以2这种简单操作的效率。

...或长答案

有两种方法:

void method1() {
    Double foo = 1.0;
    Double bar = foo * 2;
}

void method2() {
    Double foo = 1.0;
    Double bar = Double.valueOf(foo.doubleValue() * 2);
}

javac编译,用javap查看字节码指令

void method1();
   Code:
      0: dconst_1
      1: invokestatic  #2                  // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
      4: astore_1
      5: aload_1
      6: invokevirtual #3                  // Method java/lang/Double.doubleValue:()D
      9: ldc2_w        #4                  // double 2.0d
     12: dmul
     13: invokestatic  #2                  // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
     16: astore_2
     17: return

 void method2();
   Code:
      0: dconst_1
      1: invokestatic  #2                  // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
      4: astore_1
      5: aload_1
      6: invokevirtual #3                  // Method java/lang/Double.doubleValue:()D
      9: ldc2_w        #4                  // double 2.0d
     12: dmul
     13: invokestatic  #2                  // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
     16: astore_2
     17: return

你能看出区别吗?

【讨论】:

  • 正如我在对问题的评论中指出的那样,装箱转换是特定于实现的。如果您在编译器的输出中没有看到差异,并不意味着我的编译器也这样做。
【解决方案3】:

我认为无论你如何优化它,java 都会使这个版本Double bar = foo * 2; 至少和你的解决方案一样优化。试图获得这样的表现通常是徒劳的。

【讨论】:

  • 我知道这种类型的微优化是徒劳的..我只是出于好奇!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多