【发布时间】:2015-07-20 14:52:58
【问题描述】:
我的程序在 while 循环中逐行读取文本文件。然后它处理每一行并提取一些要写入输出的信息。它在 while 循环中所做的一切都是 O(1),除了我认为是 O(N) 的两个 ArrayList indexOf() 方法调用。该程序在开始时以合理的速度(每 100 秒 100 万行)运行,但随着时间的推移,它会显着减慢。我在输入文件中有 70 M 行,因此循环迭代了 7000 万次。理论上这应该需要大约 2 个小时,但实际上需要 13 个小时。问题出在哪里?
这里是sn-p的代码:
BufferedReader corpus = new BufferedReader(
new InputStreamReader(
new FileInputStream("MyCorpus.txt"),"UTF8"));
Writer outputFile = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream("output.txt"), "UTF-8"));
List<String> words = new ArrayList();
//words is being updated with relevant values here
LinkedHashMap<String,Integer> DIC = new LinkedHashMap();
//DIC is being updated with relevant key-value pairs here
String line = "";
while ((line = corpus.readLine()) != null)
String[] parts = line.split(" ");
if (DIC.containsKey(parts[0]) && DIC.containsKey(parts[1])) {
int firstIndexPlusOne = words.indexOf(parts[0])+ 1;
int secondIndexPlusOne = words.indexOf(parts[1]) +1;
outputFile.write(firstIndexPlusOne +" "+secondIndexPlusOne+" "+parts[2]+"\n");
} else {
notFound++;
outputFile.write("NULL\n");
}
}
outputFile.close();
【问题讨论】:
-
还有很多优化的空间——如果你知道
parts总是一个二元素数组,你应该使用indexOf(' ')并用substring分割,所以你有两个变量@987654325 @ 和part2。 - EDIT:忽略了parts[2]- 但它也适用于三个元素。 -
语料库有 70 M 行,每行包含三个单词。刚刚更新了代码。
-
我会说它取决于——除了 JVM 运行时优化魔法、垃圾收集器等等——取决于实际的文件内容?例如,如果在前 10M 行中 containsKey 永远不会为真,但对于剩余的 60M 行它评估为真,那么整个文件写入业务才执行,这需要大量时间。 Big-O-considerations 在这里可能没什么帮助,因为甚至涉及到 I/O。也许您可以包含一个计数器来计算和/或输出针对文件的哪些行执行了哪些代码行?
-
我想你会发现执行 I/O 消耗了 99%(可能更多)的运行时,所以归结为执行文件写入的时间,这完全取决于文件的内容。
-
你确定这就是全部代码吗? “words”和“DIC”似乎都没有更新。
标签: java while-loop time-complexity