我正在寻找最省时的方式来逐行读取 STDIN。
第一行是要测试的条件数。 以下所有行都是最多 100 000 个字符的条件(字符串)。
我已经尝试了以下(加上 4 次 90 000 个字符的结果:
带有 while 循环的扫描器(7255 毫秒)
Scanner sc = new Scanner(System.in); int numberOfLines = Integer.parseInt(sc.nextLine()); long start = 0; int i = 1; while (i<=numberOfLines){ start = System.currentTimeMillis(); sc.nextLine(); Debug.println((System.currentTimeMillis()-start) + "ms for scanner while"); i++; }
- 结果:
- 扫描仪需要 3228 毫秒,而
- 扫描仪需要 2264 毫秒,而
- 扫描仪需要 1309 毫秒
- 扫描仪需要 454 毫秒,而
- 结果:
带有 for 循环的扫描器(7078 毫秒)
Scanner sc = new Scanner(System.in); int numberOfLines = Integer.parseInt(sc.nextLine()); long start = 0; for (int i = 1; i<= numberOfLines;i++){ start = System.currentTimeMillis(); sc.nextLine(); Debug.println((System.currentTimeMillis()-start) + "ms for scanner for"); //i++; }
- 结果:
- 3168ms 用于扫描仪
- 扫描仪需要 2207 毫秒
- 1236ms 用于扫描仪
- 扫描仪需要 467 毫秒
- 结果:
带有for循环的BufferedReader (7403 ms)
try { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int numberOfLines = Integer.parseInt(br.readLine()); long start = 0; for (int i = 0; i< numberOfLines;i++){ start = System.currentTimeMillis(); br.readLine(); Debug.println((System.currentTimeMillis()-start) + "ms for bufferreader for"); //i++; } } catch (Exception e) { System.err.println("Error:" + e.getMessage());
}
- 结果:
- bufferreader 需要 3273 毫秒
- bufferreader 为 2330 毫秒
- bufferreader 需要 1293 毫秒
- bufferreader 需要 507 毫秒
- 结果:
带有 while 循环的 BufferedReader (7461 ms)
try { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int numberOfLines = Integer.parseInt(br.readLine()); int i=0; long start = 0; while(i< numberOfLines){ start = System.currentTimeMillis(); br.readLine(); Debug.println((System.currentTimeMillis()-start) + "ms for bufferreader while"); i++; } } catch (Exception e) { System.err.println("Error:" + e.getMessage());
}
- 结果:
- 3296ms for bufferreader while
- 2358ms for bufferreader while
- 1307ms for bufferreader while
- 500ms for bufferreader while
- 结果:
在调试所用时间时,我注意到每次读取后所用时间都会减少。 是否可以限制初始化的字节(例如:如果您最多有 100.000 个字符,请将扫描仪/缓冲读取器限制为仅初始化 100 000 个字符。读取后它将需要用接下来的 100 000 个字符重新填充自己)
欢迎对此事提出任何想法。
编辑:添加了每个场景的代码以及每行读取所花费的时间。还将 100.000 更改为 100 000 以更容易阅读。
最佳答案
查看 BufferedReader#readLine
源代码。我发现有几个问题:
- 它使用 StringBuffer 而不是 StringBuilder,这会产生同步开销。
- 似乎还有数据复制开销 - 不完全确定,最好检查一下。
- BufferedReader 中的专用监控对象以及更多的同步开销。
您可能会在两件事上捕获机会:
- 编写您自己的缓冲,这样可以节省一些重复复制数据的时间。
- 编写您自己的 nextLine 方法,该方法将使用 StringBuilder 并通过简单的循环遍历源数据。
关于java - 逐行读取 STDIN 的最快方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9008883/