逐行阅读STDIN的最快方式?
我正在寻找最经济有效的逐行读取STDIN的方法。
第一行是要测试的条件数。 以下所有行都是条件(字符串),最多为100 000个字符。
我已经尝试过以下内容(加上4次90 000个字符的结果:
-
带有while循环的扫描仪(7255 ms)
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++; }
- 结果:
- 扫描仪3228ms
- 扫描仪2264ms
- 扫描仪1309ms
- 扫描仪454ms
- 结果:
-
带有for循环的扫描仪(7078 ms)
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++; }
- 结果:
- 3168毫秒扫描仪
- 2207ms用于扫描仪
- 用于扫描仪的1236毫秒
- 用于扫描仪的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());
}
- 结果:
- 缓冲区读取器为3273ms
- 2330ms用于缓冲区读取器
- 缓冲区读取器为1293ms
- 缓冲区读取器为507ms
- 结果:
-
具有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
- 缓冲区读取器为2358ms
- 缓冲区读取器为1307ms
- 缓冲区读取器500ms
- 结果:
在调试所花费的时间时,我注意到每次读取后所花费的时间减少了。 是否可以限制初始化的字节数(fe:如果最多有100.000个字符,则限制扫描器/缓冲读取器仅初始化100 000个字符。读取后需要重新填充下一个100 000个字符)
关于这个问题的任何想法都非常受欢迎。
编辑:添加每个方案的代码以及每行读取的时间。 也更改了100.000到100 000更容易阅读。
查看BufferedReader#readLine
源代码。 我看到几个问题:
- 它使用StringBuffer而不是StringBuilder,这会产生同步开销。
- 此外,似乎有数据复制开销 – 不完全确定,更好地检查出来。
- BufferedReader中的专用监视器对象以及更多的同步开销。
你可以用两件事来抓住机会:
- 编写自己的缓冲,这可以节省一些时间来复制数据。
- 编写自己的nextLine方法,该方法将使用StringBuilder并以简单的周期检查源数据。