首先你对scanner.next()的使用似乎不正确. next()将返回下一个单词并在每次调用时移动到下一个单词,因此以下代码:
if(scanner.next() == null){ ... }
并且
scanner.next().replaceAll("[^A-Za-z0-9]"," ");
scanner.next().toLowerCase();
将消耗,然后只是扔掉的话.你可能想做的是:
String word = scanner.next().replaceAll("[^A-Za-z0-9]"," ").toLowerCase();
在while循环开始时,单词变量保存在单词变量中,而不是丢弃.
其次,wordCount映射的使用略有破坏.你想要做的是检查这个词是否已经在地图中,以决定要设置的字数.要做到这一点,不要检查scanner.next()== null,而应该查看地图,例如:
if(!wordCount.containsKey(word)){
//no count registered for the word yet
wordCount.put(word, 1);
}else{
wordCount.put(word, wordCount.get(word) + 1);
}
或者你可以这样做:
Integer count = wordCount.get(word);
if(count == null){
//no count registered for the word yet
wordCount.put(word, 1);
}else{
wordCount.put(word, count+1);
}
我更喜欢这种方法,因为它更清洁一点,并且每个单词只查找一个地图,而第一种方法有时会进行两次查找.
现在,要获得按频率降序排列的单词列表,您可以先将地图转换为列表,然后按照this post中的建议应用Collections.sort().以下是适合您需求的简化版本:
static List getWordInDescendingFreqOrder(Map wordCount) {
// Convert map to list of entries
List> list =
new ArrayList>(wordCount.entrySet());
// Sort list by integer values
Collections.sort(list, new Comparator>() {
public int compare(Map.Entry o1, Map.Entry o2) {
// compare o2 to o1, instead of o1 to o2, to get descending freq. order
return (o2.getValue()).compareTo(o1.getValue());
}
});
// Populate the result into a list
List result = new ArrayList();
for (Map.Entry entry : list) {
result.add(entry.getKey());
}
return result;
}
希望这可以帮助.
编辑:根据@ dragon66的建议更改了比较功能.谢谢.