【问题标题】:BigDecimal constructor performance - string vs numericBigDecimal 构造函数性能 - 字符串与数字
【发布时间】:2015-07-05 15:59:45
【问题描述】:
new BigDecimal("10000");
new BigDecimal(10000);

我知道如果数字大于编译器接受的数字,则使用字符串构造函数,但其​​中一个构造函数比另一个更快吗?

【问题讨论】:

标签: java performance bigdecimal


【解决方案1】:

可以看源码。

public BigDecimal(int val) {
    intCompact = val;
}

public BigDecimal(String val) {
    this(val.toCharArray(), 0, val.length());
}

public BigDecimal(char[] in, int offset, int len) {
       ...very long
}

显然,谁更快。

【讨论】:

    【解决方案2】:

    String 传递给BigDecimal 的构造函数需要解析String 并逐字符检查。

    传递一个 int 更快,因为它只会产生一个赋值。

    无论如何,时间差并不重要。

    这里是BigDecimal的代码,带有int参数:

    public BigDecimal(int val) {
        intCompact = val;
    }
    

    带有StringBigDecimal 构造函数的代码调用了大约有140 行代码的BigDecimal(char[], int, int)

    【讨论】:

    • 仍然想知道为什么这个 15 分钟前发布的答案没有投票,即使它比接受的答案更好。来自我的 +1。
    【解决方案3】:

    我知道如果数字比编译器接受的大,则使用字符串构造函数

    这不是使用String 构造函数的唯一原因。使用String 构造函数的另一个原因是在创建BigDecimal 时保持值不变。

    如果您真的不关心精度,您应该坚持使用double 而不是BigDecimal

    但是任何一个构造函数都比另一个更快

    这是您必须通过对代码进行基准测试自己找出的问题。话虽如此,您应该更喜欢使用valueOf 方法而不是创建新的BigDecimal,因为valueOf 将返回缓存值。 (目前,这个范围从 0 到 10,但是对于不同的 JVM 实现和 HotSpot VM 的未来实现,这个范围可能更高,所以你最好使用valueOf

    【讨论】:

      【解决方案4】:

      构造函数 new BigDecimal(10000) 应该更快,因为它不必将字符串转换为数字。在幕后必须有一个强制转换或另一个对字符串函数的调用,这会导致一些额外的开销。

      public class benchmark {
      
          public static void main(String [ ] args) {
              timeFunction();
          }
      
      static void timeFunction() {
           long startTime = System.nanoTime();
      
           BigDecimal v1 = new BigDecimal("10000");
           System.out.println("new BigDecimal(\"10000\") : " + (System.nanoTime() - startTime) / 1000000 + " ms");
      
           startTime = System.nanoTime();
      
           BigDecimal v2 = new BigDecimal(10000);
           System.out.println("new BigDecimal(10000) : " + (System.nanoTime() - startTime) / 1000000 + " ms");
      }
      
      }
      

      输出

      new BigDecimal("10000") : 4 ms
      new BigDecimal(10000) : 0 ms
      

      【讨论】:

      • 不,不,非常糟糕的方式。我会建议jmh
      • Microbenchmark 受到许多因素的强烈影响。最好的方法是在计时之前重复几次代码。但是在微基准测试中,新对象的创建确实受到垃圾收集器的影响。所以最好的办法是最终对构造函数内部的代码进行微基准测试......而不是构造函数本身
      • 我同意 Andrew 的观点,如果您想真正分析时差,这可能不是跟踪基准的最佳方法,但是,它表明使用字符串的 Big Decimal 需要更长的时间。跨度>
      【解决方案5】:

      自己找出时差并进行分析。喜欢:-

      BigDecimal big = null;
      long startTime = System.currentTimeMillis();
      for (int i = 0; i < 10000; i++) {
          big = new BigDecimal("10000");
      }
      long endTime = System.currentTimeMillis();
      System.out.println("time Taken In String : " + (endTime - startTime));
      
      startTime = System.currentTimeMillis();
      for (int i = 0; i < 10000; i++) {
          big = new BigDecimal(10000);
      }
      endTime = System.currentTimeMillis();
      System.out.println("time Taken in Numeric : " + (endTime - startTime));
      

      PS:- 请注意垃圾收集。以上代码仅供参考。

      【讨论】:

      • 该代码基准测试可能会受到垃圾收集器的严格限制。大量创建新对象的微基准测试并不可靠
      • 不,不,不好的方式。我会建议jmh
      猜你喜欢
      • 2017-12-13
      • 1970-01-01
      • 1970-01-01
      • 2014-11-21
      • 1970-01-01
      • 2018-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多