簡體   English   中英

在 Java 中打印從 Max 到 Min 的單詞出現次數(無流)

[英]Print words occurrences from Max to Min in Java (No Streams)

您能否就如何將單詞出現從最頻繁的值打印到最不頻繁的值給我建議?

我嘗試了不同的方法,所以我停在地圖上,它給了我更接近的結果。

public class InputOutput {

    private String wordsFrequency() {
        StringBuilder result = new StringBuilder();

        try {
            Map<String, Integer> map = new HashMap<>();
            BufferedReader reader = new BufferedReader(new FileReader("words.txt"));
            String words;

            while ((words = reader.readLine()) != null) {
                Scanner scan = new Scanner(words);
                while (scan.hasNext()) {
                    String word = scan.next();
                    if (map.containsKey(word))
                        map.put(word, map.get(word) + 1);
                    else
                        map.put(word, 1);
                }
                scan.close();
            }
            reader.close();
            Set<Entry<String, Integer>> entrySet = map.entrySet();

            for (Entry<String, Integer> entry : entrySet) {
                result.append(entry.getKey()).append("\t").append(entry.getValue()).append("\n");
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return result.toString();

    }

    public static void main(String[] args) {
        InputOutput requestedData = new InputOutput();

        System.out.println(requestedData.wordsFrequency());

    }
}

文件內容:

the day is sunny the the
the sunny is is is is is is

預期輸出:

is  7
the 4
sunny   2
day 1

我得到的輸出:

the 4
is  7
sunny   2
day 1
List<Map.Entry<String, Integer>> frequencies = new ArrayList<>(map.entrySet());
frequencies.sort(Comparator.comparing(e -> e.getValue()).reversed());

可以對 List 進行排序,也可以使用 Comparator 對 TreeSet 進行排序(SortedSet)。 這里有一個返回 Comparable 值的函數。

我敢肯定有一種更清潔的方法可以做到這一點,但不使用流,這就是我想出的:

String src = "the day is sunny the the the sunny is is is is is is";

try (Scanner scanner = new Scanner(new StringReader(src))) {
    Map<String, Integer> map = new HashMap<>();
    while (scanner.hasNext()) {
        String word = scanner.next();
        map.merge(word, 1, (a, b) -> a + 1);
    }
    Map<Integer, Collection<String>> cntMap = new TreeMap<>(Comparators.reverseOrder());
        
    for (Entry<String, Integer> entry : map.entrySet()) {
       Collection<String> list = cntMap.get(entry.getValue());
       if (list == null) {
           list = new TreeSet<>();
           cntMap.put(entry.getValue(), list);
       }
       list.add(entry.getKey());
    }

    for (Entry<Integer, Collection<String>> entry : cntMap.entrySet()) {
       System.out.println(entry.getValue() + " : " + entry.getKey());
    }
}

您提供的代碼的問題:

  • 如果出現異常,則不會關閉流。 更重要的是,如果所有數據都可以從文件中成功讀取,但在關閉閱讀器期間發生異常,您將獲得數據,因為負責處理地圖的代碼行將不會被執行。 對資源使用 try以確保您的資源將正確關閉。

  • 不要在一種方法中塞進太多邏輯。 正如單一職責原則所建議的那樣,至少有兩個職責,它們應該存在於不同的方法中。

  • 您可以拆分從文件中讀取的行,而不是使用Scanner

  • 而且您當前的邏輯很幸運排序。 這就是您當前和預期的輸出不匹配的原因。

您可以生成一個地圖Map<String, Integer>表示每個單詞的頻率。

然后創建此地圖的條目列表,根據值按降序對其進行排序。

最后將排序的條目列表轉換為可以打印的字符串列表

private static Map<String, Integer> wordsFrequency(String file) {
    
    Map<String, Integer> frequencies = new HashMap<>();
    
    try (var reader = Files.newBufferedReader(Path.of(file))) {
        String[] words = reader.readLine().split(" ");
        for (String word : words) {
        //  frequencies.merge(word, 1, Integer::sum); // an equivalent of the 2 lines below
            int count = frequencies.getOrDefault(word, 0);
            frequencies.put(word, count + 1);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    
    return frequencies;
}

public static List<String> mapToSortedList(Map<String, Integer> map) {
    List<Map.Entry<String, Integer>> entries = new ArrayList<>(map.entrySet());
    // sorting the list of entries
    entries.sort(Map.Entry.<String, Integer>comparingByValue().reversed());
    
    List<String> result = new ArrayList<>();
    for (Map.Entry<String, Integer> entry :entries) {
        result.add(entry.getKey() + " " + entry.getValue());
    }
    return result;
}

public static void main(String[] args) {
    mapToSortedList(wordsFrequency("filePath.txt")).forEach(System.out::println);
}

您已經有了數據,這里是如何以反向排序的順序獲取它們。

  • 使用比較器聲明一個SortedSet來比較條目的值
  • 然后將條目添加到SortedSet中,它們將在輸入時進行排序。
  • Entry.comparingByValue(Comparator.reversed())用於僅按計數和倒序排序。
SortedSet<Entry<String,Integer>> set
            = new TreeSet(Entry.comparingByValue(Comparator.reverseOrder()));
set.addAll(map.entrySet());

然后打印它們。

set.forEach(e-> System.out.printf("%-7s : %d%n", e.getKey(), e.getValue()));

對於您的數據,這將打印

is      : 7
the     : 4
sunny   : 2
day     : 1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM