2012-02-14 36 views
2

我一直在閱讀地圖,並瞭解樹圖和散列排序地圖的一些差異。我試圖在輸出地圖時對其進行排序。排序映射不輸出排序。我瞭解地圖嗎?

我需要什麼,能夠做的是:

  1. 以一個文本文件,並在內容閱讀。
  2. 將其分成單獨的單詞。使用單詞作爲關鍵字,並將該值作爲txt文件中發生的次數key
  3. 如果這個單詞在一個句子的末尾,我將它作爲一個單獨的密鑰。例如,mymy.是兩個獨立的鍵。

我的問題是,無論我將它聲明爲樹,散列還是有序映射,我都無法以有序的方式輸出/遍歷。我希望它先輸出最高的值,但我甚至無法以任何順序使用密鑰輸出。

public static Map<String, Integer> createDictionary(String _filename) 
{ 
    TreeMap<String, Integer> dictionary = new TreeMap<String, Integer>(); // Changed Hash to _______ 

    try { 
      FileReader myFileReader=new FileReader(_filename); // File reader stream open 
      BufferedReader myBuffReader=new BufferedReader(myFileReader); 

      String str = "\0"; 

      while (str != null) { // While there are still strings in the file 
       str = myBuffReader.readLine(); // We read a line into the str variable 

       if (str != null) { // Make sure its not the last line/EOF 
        // System.out.println(str); // Used for testing. 
        StringTokenizer myTokenStr=new StringTokenizer(str," \t"); // Create a StringToken obj from the string 

        while (myTokenStr.hasMoreTokens()) { 
         String tokStr = myTokenStr.nextToken(); // Each token is put into an individual string 
         // System.out.println(tokStr); 

         if (dictionary.containsKey(tokStr)) { 
          int value = dictionary.get(tokStr); // Add one to the integer value 
          // dictionary.remove(tokStr); // Was doing this way but just using put method works 
          // dictionary.put(tokStr, value + 1); 
          dictionary.put(tokStr, value + 1); 
         } 
         else { 
          dictionary.put(tokStr, 1); // Add the string as the key with an int value of one for the value 
         } 
        } 
       } 
      } 

      myBuffReader.close(); // Close stream 
      myFileReader.close(); // Close stream 
     } 
     catch (FileNotFoundException e) { 
      System.out.println("File Not Found"); 
     } 
     catch (IOException e) { } 

     // System.out.println(dictionary.entrySet()); 

     return dictionary; 
} 
+0

那麼......它輸出什麼? – StilesCrisis 2012-02-14 04:36:42

+0

首先,你確定要在'「\ t」'上標記嗎?當你說「闖入單詞」時,默認的標記字符串在一般情況下似乎是更好的匹配,即'StringTokenizer(str)'你不像符號化的方式匹配換行符。你究竟如何迭代? (另外,如果你想排序,忘記HashMap,TreeMap是唯一的方法) – Irfy 2012-02-14 04:40:06

+0

Stiles ...它輸出正確的單詞與正確的單詞計數,但下面的單詞是按字母順序或值/單詞計數在訂購。它的隨機像一個哈希映射。 Irfy .... tokinize on「\ t」應該標記爲空格和製表符。唯一的另一個就是行尾,這已經被照顧了。我可能是錯的,但它與C++ tokinize類似,它已與我發送它的測試用例一起工作。 – 2012-02-14 05:05:12

回答

0

您的地圖按字母順序排列,而不是按出現次數排序。您需要在初始解析後處理地圖。我建議:

  1. 解析文件到HashMap<String, Integer>
  2. 迭代通過HashMap,並添加元素爲TreeMap<Integer, Set<String> >(見下文)。
  3. 輸出TreeMap

    TreeMap<Integer, Set<String> > treeMap = new TreeMap<Integer, Set<String> >(); 
    for (Map.Entry<String, Integer> entry: hashMap) { 
        Set<String> set = treeMap.get(entry.value()); 
        if (set == null) { 
         set = new TreeSet<String>(); 
         treeMap.put(entry.value(), set); 
        } 
        set.add(entry.key()); 
    } 
    

    使用TreeSet這裏排序與相同數量出現字母的話,你可以使用任何其他SetList雖然:

您可以像實現步驟2。

對於步驟3中的降序。:

for (Map.Entry<Integer, Set<String> > entry: treeMap.descendingMap()) 
    for (String word: entry.getValue()) 
     System.out.println(String.format("%d: %s", entry.getKey(), word)); 

應該這樣做。

+1

如果兩個單詞具有相同的計數會發生什麼? – 2012-02-14 05:03:40

+0

好點。我想如果沒有'TreeMap >'和一些額外的代碼來創建列表並追加它,如果它存在的話,它將無法工作。 – Irfy 2012-02-14 05:05:47

0

這是樹形圖中的文件,從它的Javadoc解禁:

 

public class TreeMap extends AbstractMap 
    implements NavigableMap, Cloneable, Serializable 

A Red-Black tree based NavigableMap implementation. The map is sorted according 
to the natural ordering of its keys, or by a Comparator provided at map creation 
time, depending on which constructor is used. 

在你的情況下,密鑰將是字符串,你應該預料到迭代將顯示在地圖根據排序到他們的「自然秩序」。下面是通過由字符串鍵和整數值的一個TreeMap產生的輸出的一個示例:

Map<String, Integer> map = new TreeMap<String, Integer>(); 
map.put("Hello", Integer.valueOf(8)); 
map.put("Abraham", Integer.valueOf(81)); 
map.put("Smell", Integer.valueOf(-1)); 
map.put("Carpet", Integer.valueOf(4)); 
map.put("Sex", Integer.valueOf(23)); 

for(String key: map.keySet()) { 
    System.out.printf("Map entry %s: %d\n", key, map.get(key)); 
} 

輸出:

Map entry Abraham: 81 
Map entry Carpet: 4 
Map entry Hello: 8 
Map entry Sex: 23 
Map entry Smell: -1 

正如你可以看到,遍歷地圖的鍵產生作爲排序的結果。這個順序是由String的自然順序定義的。不幸的是,你不能實現SortedMap的排序值,這是我相信你想要做的。但是,您可以對其外部的地圖中的條目進行排序。在其他SO貼子中看到更多細節:TreeMap sort by value

+0

如果我將地圖更改爲TreeMaps,並使用與發佈相同的方式遍歷它,則它不會像您展示的那樣給出和排序輸​​出。這是我的問題的一部分。從我閱讀到我所看到的他們不一樣。看看我的代碼是否有一些關於如何通過可能正在執行的地圖迭代的內容。我完全不理解迭代器的用法。 – 2012-02-14 05:11:24

+0

@aaronburns - 你的代碼看起來基本沒問題。嘗試在將字符串存儲在地圖中之前調用字符串「trim()」。 – Perception 2012-02-14 05:14:44

0

Map對於這種事情是一種凌亂的抽象,但我打算拋出番石榴的Multiset作爲解決此用例的一種方式,因爲它明確地設計用於「計數事物的發生」。

特別地,

return Multisets.copyHighestCountFirst(HashMultiset.copyOf(listOfWords)); 

返回Multiset該迭代元件在listOfWords按頻率的降序。

在SO上有很多問題,順便說一句,有關排序地圖而不是鍵,但我更喜歡this solution