Java OutputStream打印速度

问题描述

假设我必须打印一个用逗号分隔值的数组arr。现在,我正在执行以下操作:

for(int i = 0;i<arr.length;i++) {
    System.out.print(arr[i] + ",");
}

但是,对于大的arr长度,我想知道这是否真的很慢。我想到的第二种方法是使用StringBuilder,并仅使用1条print语句构造最终的输出字符串。那值得吗?权衡将是更复杂的代码

如果有关系,我想回答打印到控制台并打印到文件的问题。

解决方法

此代码效率不高,因为每次计算arr[i] + ","时都必须实例化一个新的String,这需要分配一个新的内存插槽,并在完成后用垃圾回收器丢弃旧字符串。

Dave Newton 提供的解决方案是打印阵列的最有效方法。我已经对包含2万个元素的数组做了一个小小的基准测试(我在小型PC上可以选择的最大数量,因为如果数组太大,显示数组往往会扭曲计算时间):

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        String[] array = new String[20000];
        Arrays.fill(array,"A");

        long t0 = System.currentTimeMillis();

        /* Test 1 : using a for loop */
        for (int i = 0; i < array.length; i++)
            System.out.print(array[i] + ",");
    
        System.out.println();
        long t1 = System.currentTimeMillis();

        /* Test 2 : using a for-each loop */
        for (String a : array)
            System.out.print(a + ",");
    
        System.out.println();
        long t2 = System.currentTimeMillis();

        /* Test 3 : using String.join */
        System.out.println(String.join(",",array));
        long t3 = System.currentTimeMillis();
    
        System.out.println("Test 1 : " + (t1 - t0) + "ms");
        System.out.println("Test 2 : " + (t2 - t1) + "ms");
        System.out.println("Test 3 : " + (t3 - t2) + "ms");
    }
}

我得到以下结果:

Test 1 : 110ms
Test 2 : 93ms
Test 3 : 0ms

This website解释了原因。 String.join生成一个StringJoiner实例,该实例将字符存储在StringBuilder中。

StringBuilder充当缓冲区;将String附加到缓冲区中然后显示结果比多次实例化2 String的总和要有效得多。