【问题标题】:How to reduce time taken by System.out.println();如何减少 System.out.println() 花费的时间;
【发布时间】:2017-01-18 13:44:19
【问题描述】:

我在列表中插入 2_000_000 个长值。每次插入时,我都需要使用 SOP 将列表的大小打印到控制台。如果我不打印尺寸来控制台插入将在 250 毫秒内完成。如果我每次插入一个值时都打印大小,则所用时间为 25000 毫秒。

知道如何解决这个性能问题吗?

我正在使用 Java7 和 Eclipse (kepler) 来测试我的实现。

注意:每次插入 long 值时都打印大小是问题定义所必需且强制的。

【问题讨论】:

  • 您的问题是您向控制台提交了如此多的打印请求。建立所有列表长度的字符串并在最后提交会快得多。
  • 如果要求每次都打印并且这意味着控制台/进程输出中的结果可见,那么您无能为力。所有建议缓冲的解决方案都意味着消息将在以后看到。当然,当总执行时间为 250 毫秒时,人类读者不会注意到延迟。

标签: java performance io


【解决方案1】:

尝试使用BufferedWriter。它允许高效的字符书写。 另外,最后不要忘记调用flush方法,以便输出所有缓冲的数据。

工作示例:

    List<Long> list = new ArrayList<>();
    try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out))) {
        for(long i = 0; i < 2000000; i++) {
            list.add(i);
            bw.write("Current size:" + list.size());
            bw.newLine();
            if(i % 100 == 0 || i == 1999999) {
                bw.flush();
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

第二个选项可能是使用StringBuilder

    List<Long> list = new ArrayList<>();
    String separator = System.getProperty("line.separator");
    int initialCapacity = 200000;
    StringBuilder sb = new StringBuilder(initialCapacity);
    for (long i = 0; i < 2000000; i++) {
        list.add(i);
        sb.append("Current size:").append(list.size()).append(separator);
        if (i % 10000 == 0 || i == 1999999) {
            System.out.println(sb);
            sb = new StringBuilder(initialCapacity);
        }
    }

【讨论】:

  • 而且……第二个解决方案仍然比第一个慢吗?
  • 不,第二个解决方案现在更快(在我的计算机上大约快 20%)。
【解决方案2】:

例如

BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
for (long myLong : values)
{
    list.add(myLong);
    writer.write(list.size());
}

一旦你完全完成,或者每 1000 次插入,调用

writer.flush();

【讨论】:

    猜你喜欢
    • 2020-06-05
    • 1970-01-01
    • 2020-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多