将Java中的数字填充到一定数量的数字的最快方法

Mar*_*tin 2 java performance stringbuilder substring digits

我试图根据DB生成的序列号(Y)创建一个经过良好优化的代码位来创建长度为X位的数字(其中X是从运行时属性文件中读取的),然后使用一个文件夹保存文件时的-name.

到目前为止,我已经提出了三个想法,其中最快的是最后一个,但我很欣赏人们可能对此提出的任何建议......

1)实例化具有初始容量X的StringBuilder.追加Y.当长度<X时,在零位置插入零.

2)实例化具有初始容量X的StringBuilder.当长度<X时,追加零.根据StringBuilder值创建DecimalFormat,然后在需要时格式化数字.

3)创建Math.pow(10,X)的新int并添加Y.对新数字使用String.valueOf(),然后对其进行子串(1).

第二个显然可以分为外环和内环部分.

那么,有什么提示吗?使用10,000次迭代的for循环,我从前两个获得类似的时序,第三个方法大约快十倍.这看起来是否正确?

完整的测试方法代码如下......

    // Setup test variables
    int numDigits = 9;
    int testNumber = 724;
    int numIterations = 10000;
    String folderHolder = null;
    DecimalFormat outputFormat = new DecimalFormat( "#,##0" );

    // StringBuilder test
    long before = System.nanoTime();
    for ( int i = 0; i < numIterations; i++ )
    {
        StringBuilder sb = new StringBuilder( numDigits );
        sb.append( testNumber );
        while ( sb.length() < numDigits )
        {
            sb.insert( 0, 0 );
        }

        folderHolder = sb.toString();
    }
    long after = System.nanoTime();
    System.out.println( "01: " + outputFormat.format( after - before ) + " nanoseconds" );
    System.out.println( "Sanity check: Folder = \"" + folderHolder + "\"" );

    // DecimalFormat test
    before = System.nanoTime();
    StringBuilder sb = new StringBuilder( numDigits );
    while ( sb.length() < numDigits )
    {
        sb.append( 0 );
    }
    DecimalFormat formatter = new DecimalFormat( sb.toString() );
    for ( int i = 0; i < numIterations; i++ )
    {
        folderHolder = formatter.format( testNumber );
    }
    after = System.nanoTime();
    System.out.println( "02: " + outputFormat.format( after - before ) + " nanoseconds" );
    System.out.println( "Sanity check: Folder = \"" + folderHolder + "\"" );

    // Substring test
    before = System.nanoTime();
    int baseNum = (int)Math.pow( 10, numDigits );
    for ( int i = 0; i < numIterations; i++ )
    {
        int newNum = baseNum + testNumber;
        folderHolder = String.valueOf( newNum ).substring( 1 );
    }
    after = System.nanoTime();
    System.out.println( "03: " + outputFormat.format( after - before ) + " nanoseconds" );
    System.out.println( "Sanity check: Folder = \"" + folderHolder + "\"" );
Run Code Online (Sandbox Code Playgroud)

aio*_*obe 7

我会停止基于微基准测试进行优化,并寻找代码优雅的东西,例如 String.format("%0"+numDigits+"d", testNumber)

  • @Martin:您说您正在使用此例程生成文件或目录名称.如果考虑磁盘访问所需的时间,您认为"优化"这部分代码的重要性有多大? (3认同)
  • 在解释微基准测试数据时应该小心.在某些情况下,如果编译器/ JIT编译器意识到它是不必要的,那么它会优化大块代码.例如,很明显,(在第三种情况下)`newNum`将在所有迭代中保持不变.这可能反过来导致`String.valueOf(newNum).substring(1);`被置于循环之外,这会破坏整个基准. (2认同)
  • 尝试在每次迭代中添加文件夹(名称为`folderHolder`)的实际创建.你在测试之间获得相同的百分比差异吗?或者文件夹名称的计算可以忽略不计? (2认同)