繁体   English   中英

为什么Java List遍历比文件readline慢?

[英]Why is Java List traversal slower than file readline?

我有这段代码:

while((line=br.readLine())!=null)
        {
            String Words[]= line.split(" ");
            outputLine = SomeAlgorithm(Words);
            output.write(outputLine);
        }

正如您在上面的代码中看到的,对于输入文件中的每一行,我正在读取一行,在其上运行一些算法,基本上修改该行读取,然后将输出行写入某个文件。

文件中有9k行,整个程序在我的机器上花了3分钟。

我想,好吧,我正在为算法的每个(行)运行做2个I / O. 所以我做了大约18k I / O. 为什么不首先将所有行收集到ArrayList ,然后遍历列表并在每一行上运行算法? 还将每个输出收集到一个字符串变量中,然后在程序结束时写出所有输出一次。

这样,我整个程序总共有2个大I / O(18k小文件I / O到2个大文件I / O)。 我觉得这会更快,所以我写了这个:

List<String> lines = new ArrayList<String>();
while((line=br.readLine())!=null)
        {
            lines.add(line); // collect all lines first
        }

for (String line : lines){
    String Words[] = line.split(" ");
    bigOutput+=SomeAlgorithm(Words); // collect all output
}

output.write(bigOutput);

但是,这件事需要7分钟

那么,为什么循环遍历ArrayList比逐行读取文件要慢?

注意:通过readLine()收集所有行并写入bigOutput都只需要几秒钟。 SomeAlgorithm()也没有变化。 所以,当然,我认为罪魁祸首是for (String line: lines)

更新:正如下面各种评论中所提到的,问题不在于ArrayList遍历,而是使用+ =累积输出的方式。 转移到StringBuilder()确实给出了比原始结果更快的结果。

我怀疑性能的差异是由于你如何在一个变量( bigOutput )中收集输出。 我的猜想是,这涉及大量的内存重新分配和字符数据的复制,这是缓慢的真正原因。

这取决于文件的大小,但是这里可能发生的事情是,调整ArrayList存储和连接字符串需要的时间比执行大量小文件操作要多。

请记住,磁盘和操作系统都执行某种级别的I / O缓存,其中一些涉及预读(期望您可能会按顺序读取数据),因此第一次读取可能会填充相当多将文件的一部分放入I / O缓存中,从中可以非常快速地读取。

因此,您需要从I / O高速缓存中进行小读取,以获得许多平面数组调整( ArrayList和输出sting),每次调整都变得越来越慢。

tl; dr版本:让各种I / O缓存完成它们的工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM