如何从 HashMap 中仅打印前 10 个单词及其出现频率?

How to print just the top 10 words and their frequency from a HashMap?

我的代码有问题。 我正在阅读一个包含一些文本的文件,然后计算单词及其频率。然后我试图打印出文本中最常用的前 10 个单词。

但是,使用我尝试过的方法(例如,将 for 循环设置为在 10 次迭代后停止),我只以相同的方式打印了 10 次单词。否则,我可以使用 frequency.I 打印文件中的所有单词,只需要前 10 个最常用的单词。

ArrayList<Integer> values = new ArrayList<>();
    values.addAll(wordcount.values());
    Collections.sort(values, Collections.reverseOrder());
    int last_i = -1;
    for(Integer i: values) {
        if (last_i == i)
            continue;
        last_i = i;
        System.out.println("The top 10 words are: ");
       // for (int count = 0; count < 10; count++) {
            for (String s : wordcount.keySet())
                if (wordcount.get(s) == i)
                    System.out.println(s + " : " + i);
           }
       }
}

请在上方找到 "problematic" 代码。我正在使用

BufferedReader

读取文本文件,然后删除所有标点符号和可能导致同一个词在我的 HashMap 中显示为两个不同条目的内容。

非常感谢您的帮助。谢谢!

这是一个 Java 8 的 lambda 示例:

        Map<String, Integer> wordcount = new HashMap<>();
        wordcount.put("two", 20);
        wordcount.put("five", 50);
        wordcount.put("three", 30);
        wordcount.put("four", 40);
        wordcount.put("one", 10);
        wordcount.put("six", 60);
        wordcount.put("eight", 80);
        wordcount.put("twelve", 1);
        wordcount.put("nine", 90);
        wordcount.put("ten", 100);
        wordcount.put("seven", 70);
        wordcount.put("eleven", 1);
        wordcount.put("15", 1);
        wordcount.put("13", 2);
        wordcount.put("16", 4);
        wordcount.put("14", 3);
        wordcount.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByValue(Collections.reverseOrder()))
                .limit(10)
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (e1, e2) -> e1,
                        LinkedHashMap::new
                )).forEach((s, integer) -> System.out.println(String.format("%s : %s", s, integer)));

应该打印如下内容:

ten : 100
nine : 90
eight : 80
seven : 70
six : 60
five : 50
four : 40
three : 30
two : 20
one : 10

首先,您需要借助 Map 计算每个单词在文本中重复的次数,然后以相反的顺序对 map 条目进行排序,因为最频繁出现的单词将位于集合的开头并首先打印此系列中的十个元素。

public void printTopTenWordsByFrequencyFrom(List<String> text) {
    Map<String, Integer> map = new HashMap<>();
    for(String word : text) {
        Integer times = map.get(word);
        if(times == null) {
            map.put(word, 1);
        } else {
            map.put(word, times + 1);
        }
    }
    map.entrySet().stream()
                  .sorted((one, another) -> - one.getValue().compareTo(another.getValue())) //sort entries to reverse order  
                  .limit(10) 
                  .forEach(entry -> entry.getKey() + " : " + entry.getValue());
}

没有流和 lambda 的版本:

  public void printTopTenWordsByFrequencyFrom(List<String> text) {
        Map<String, Integer> map = new HashMap<>();
        for(String word : text) {
            Integer times = map.get(word);
            if(times == null) {
                map.put(word, 1);
            } else {
                map.put(word, times + 1);
            }
        }
        List<Map.Entry<String, Integer>> statistics = new ArrayList<>(map.entrySet());
        Collections.sort(statistics, new Comparator<Map.Entry<String, Integer> {

            int compare(Map.Entry<String, Integer> one, Map.Entry<String, Integer> another) {
                return - one.getValue().compareTo(another.getValue()); 
            }
        });
        List<Map.Entry<String, Integer>> topTen = statistics.sublist(0, 9);
        for(Map.Entry<String, Integer> word : topTen) {
            System.out.println(word.getKey() + " : " + word.getValue());
        }
    }