Java输出流打印速度

huangapple go评论70阅读模式
英文:

Java OutputStream printing speed

问题

假设我需要打印一个带有逗号分隔值的数组 arr。目前,我正在执行以下操作:

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

然而,对于很大的 arr 长度,我在想这样做可能会非常慢。我心里考虑的第二种方法是使用 StringBuilder,构建最终的输出字符串,并且只使用一个打印语句。这样做是否值得一试?权衡之处在于代码会变得更加复杂。

如果有影响的话,我希望得到关于在控制台打印和打印到文件的答案。

英文:

Suppose I had to print an array arr with comma-separated values. Right now, I am doing the following:

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

However, for large arr lengths, I was wondering if this might be really slow. A second approach I had in mind was using StringBuilder, and constructing the final output string and only using 1 print statement. Would that be worth going for? The tradeoff would be more complicated code.

If it matters, I would like an answer for printing to console and printing to a file.

答案1

得分: 1

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

Dave Newton 提供的解决方案是打印数组的最有效方法。我使用一个包含 20,000 个元素的数组进行了小型基准测试(这是我在小型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();

        /* 测试 1:使用 for 循环 */
        for (int i = 0; i < array.length; i++)
            System.out.print(array[i] + ",");
        
        System.out.println();
        long t1 = System.currentTimeMillis();

        /* 测试 2:使用 for-each 循环 */
        for (String a : array)
            System.out.print(a + ",");
        
        System.out.println();
        long t2 = System.currentTimeMillis();

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

我得到了以下结果:

测试 1:110ms
测试 2:93ms
测试 3:0ms

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

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

英文:

This code isn't efficient because you have to instantiate a new String each time you calculate arr[i] + &quot;,&quot;, which requires to allocate a new memory slot and discard the old string with the garbage collector when it's done.

The solution given by Dave Newton is the most efficient way to print your array. I've made a little benchmark with an array containing 20 000 elements (the biggest number I can choose in my small PC because displaying the array tends to distort the computing time when the array is too big):

import java.util.Arrays;

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

	    long t0 = System.currentTimeMillis();

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

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

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

I have the following results:

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

This website explains the reason. String.join generates a StringJoiner instance which stores characters in a StringBuilder.

StringBuilder works as a buffer; appending Strings in a buffer then display the result is way more efficient than instantiating the sum of 2 Strings multiple times.

huangapple
  • 本文由 发表于 2020年10月10日 03:29:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/64286196.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定