我正在寻找最省时的方式来逐行读取 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++;
}
- Results :
- 扫描仪为 3228ms,同时
- 扫描仪为 2264ms,同时
- 扫描仪需要 1309ms
- 扫描仪为 454ms,同时
-
带 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++;
}
- Results :
- 扫描仪为 3168ms
- 扫描仪为 2207ms
- 扫描仪为 1236ms
- 扫描仪为 467ms
-
具有 for 循环的 BufferedReader(7403 毫秒)
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());
}
- Results :
- 缓冲区读取器为 3273ms
- 缓冲区读取器为 2330ms
- 缓冲区读取器为 1293ms
- 缓冲区读取器为 507ms
-
带有 while 循环的 BufferedReader(7461 毫秒)
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());
}
- Results :
- 缓冲区读取器需要 3296 毫秒,而
- bufferedreader 为 2358 毫秒,同时
- bufferedreader 为 1307 毫秒
- 缓冲区读取器为 500ms,同时
在调试所花费的时间时,我注意到每次读取后所花费的时间都会减少。
是否可以限制初始化的字节(例如:如果最多有 100,000 个字符,请将扫描仪/缓冲读取器限制为仅初始化 100,000 个字符。读取后,它将需要用接下来的 100,000 个字符重新填充)
关于这个问题的任何想法都非常受欢迎。
编辑:添加了每个场景的代码以及每行读取所花费的时间。还将 100.000 更改为 100 000 以更容易阅读。
向里面看去BufferedReader#readLine
来源。我看到有几个问题:
- 它使用 StringBuffer 而不是 StringBuilder,这会产生同步开销。
- 另外似乎还有数据复制开销 - 不完全确定,最好检查一下。
- BufferedReader 中的专用监视对象甚至会产生更多的同步开销。
你可以在两件事上抓住机会:
- 编写自己的缓冲,这可以节省数据双重复制的时间。
- 编写您自己的 nextLine 方法,该方法将使用 StringBuilder 并通过简单的循环遍历源数据。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)