【发布时间】:2018-09-23 18:20:09
【问题描述】:
所以这里的程序计算文本文档中出现次数最多的单词的出现。然而,由于我认为的 get(i) 方法,它非常慢。任何想法如何使它更快?我知道如果我使用数组会更快,但我希望它保持为链表,如果可能的话,只需更改 get(i) 部分。
import java.io.File;
import java.util.Scanner;
import java.util.Map.Entry;
import java.util.AbstractMap;
import java.util.LinkedList;
public class wordcount {
public static Entry<String, Integer> count_LINKED_LIST(String[] tokens) {
LinkedList<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>();
for (int j = 0; j < tokens.length; j++) {
String word = tokens[j];
boolean found = false;
for (int i = 0; i < list.size(); i++) {
Entry<String, Integer> e = list.get(i);
if (word.equals(e.getKey())) {
e.setValue(e.getValue() + 1);
list.set(i, e);
found = true;
break;
}
}
if (!found)
list.add(new AbstractMap.SimpleEntry<String, Integer>(word, 1));
}
int maxCount = 0;
String maxWord = "";
for (int i = 0; i < list.size(); i++) {
int count = list.get(i).getValue();
if (count > maxCount) {
maxWord = list.get(i).getKey();
maxCount = count;
}
}
return new AbstractMap.SimpleEntry<String, Integer>(maxWord, maxCount);
}
static String[] readText(String PATH) throws Exception {
Scanner doc = new Scanner(new File(PATH)).useDelimiter("[^a-zA-Z]+");
int length = 0;
while (doc.hasNext()) {
doc.next();
length++;
}
String[] tokens = new String[length];
Scanner s = new Scanner(new File(PATH)).useDelimiter("[^a-zA-Z]+");
length = 0;
while (s.hasNext()) {
tokens[length] = s.next().toLowerCase();
length++;
}
doc.close();
return tokens;
}
public static void main(String[] args) throws Exception {
String PATH = "/Users/username/foldername/textdocument.txt";
String[] tokens = readText(PATH);
long startTime = System.currentTimeMillis();
Entry<String, Integer> entry = count_LINKED_LIST(tokens);
long endTime = System.currentTimeMillis();
String time = String.format("%12d", endTime - startTime);
System.out.println("time\t" + time + "\t" + entry.getKey() + ":" + entry.getValue());
}
}
【问题讨论】:
-
您是否尝试过使用 for each 循环?
-
get(int i)在LinkedList上非常慢,因为它必须从头开始扫描以定位索引i。要使其更快,请使用ArrayList。但是,实际上要快速实现“计算出现次数最多的单词的出现次数”,请使用Map<String, Integer>。 -
LinkedList 是您可以为此任务选择的最糟糕的集合(实际上对于任何任务),并且您通过使用索引来访问元素以极其低效的方式使用它,首先获取元素,然后设置它们(尽管这完全没有必要)。使用适当的数据结构:HashMap。
-
@FallaCoulibaly 使用迭代器循环或 foreach 循环可能会更快。但是 HashMap 确实更合适。
-
@JBNizet 我不同意“事实上,对于任何任务来说,链表都是最糟糕的集合”。例如,链接列表对于编程来说是非常基础的,并且用于在您的操作系统中实现哈希和任务队列。确实,它不适合 this 任务,也许您正在专门讨论 Java 的 LL 集合实现。当您需要暗示访问前后元素时,使用 LinkedList 而不是 ArrayList 可能是合适的,例如在队列和堆栈中。如果您使用的是
list.get方法,则可能是结构错误。
标签: java