2013-10-25 49 views
0

使用以下代碼創建一個hashmap,然後使用樹形圖和比較器對hashmap中的值進行排序。但是,輸出是相當意想不到的。 因此,任何想法,以什麼林做錯了會很有幫助使用TreeMap和比較器按值排序HashMap

代碼

public static void main(String[] args) { 
    System.out.println("Most freq"+mostFreq(" i me hello hello hello me")); 
} 


public static String[] mostFreq(String str){ 

    if ((str==null)||(str.trim().equalsIgnoreCase(""))) 
     return null; 

    String[] arr = new String[10]; 

    String[] words= str.split(" "); 

    Map <String,Integer> map = new HashMap<String,Integer>(); 

    for (String word :words) 
    { 
     int count =0; 
     if (map.containsKey(word)) 
     {  
      count= map.get(word); 
      map.put(word, count+1); 
     }    
     else 
      map.put(word, 1); 
    } 

    MyComparator comp= new MyComparator(map); 
    Map<String,Integer> newMap= new TreeMap(comp); 
    newMap.putAll(map); 
    Iterator it= newMap.entrySet().iterator(); 
    while (it.hasNext()) 
    { 
     Map.Entry pairs = (Map.Entry) it.next(); 
     System.out.println("Key "+pairs.getKey()+"-- value"+pairs.getValue()); 
    } 

    return arr; 
} 

這裏是比較

package samplecodes; 

import java.util.Comparator; 
import java.util.Map; 

public class MyComparator implements Comparator { 

    Map map; 

    public MyComparator(Map map){ 
     this.map=map; 
    } 

    @Override 
    public int compare(Object o1, Object o2) { 
     return ((Integer)map.get(o1) >(Integer)map.get(o2)? (Integer)map.get(o1):(Integer)map.get(o2)); 
    } 

} 

和輸出的形式

me-2 
hello-3 
i-3 
+0

您的代碼不會生成此輸出。你確定這是你正在使用的? – Pshemo

+1

也可以看看[在Java中如何對數據進行排序,然後進行排序](http://stackoverflow.com/questions/109383/how-to-sort-a -code-value-on-the-values-in-java) – Pshemo

+1

你的代碼中有很多難聞的氣味:請爲你的Map,Iterator等添加泛型類型參數。在'mostFreq()'你正在返回'arr'只是一個空字符串數組,在方法中從未被觸及過。我也在回答關於你的邏輯問題的回答 –

回答

3

的請檢查compare的JavaDoc:你不回大GER的值,但對於-1o1 < o20o1 = o21o1>o2。所以,你可以寫:

@Override 
public int compare(Object o1, Object o2) { 
    return ((Integer) map.get(o1)).compareTo((Integer) map.get(o2); 
} 
+0

啊。我的錯。但我認爲這樣做手動即。 'if(o1 == o2)return 0; \t return(Integer)map.get(o1)>(Integer)map.get(o2)? 1:-1;當你需要所有單詞的頻率時,'是一個更好的選擇。使用'compareTo'似乎抑制了相同頻率的單詞。 – KodeSeeker

+0

你是對的;我沒有想到這一點。但在其他情況下,將比較委託給其他類很好。 ;) –

+0

@KodeSeeker我認爲你的評論邏輯是錯誤的。 IIRC'compare()'應該是「對稱的」http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html#compare%28T,%20T%29:sgn(compare( a,b))應該返回-sgn(比較(b,a))。但是,您的邏輯不會:如果鍵「o1」和「o2」的映射中的值相同,則比較(a,b)和比較(b,a)返回1,這違反了合同。 –

1

TreeMapJava Doc明確指出:

紅黑樹基於NavigableMap實現。該地圖是根據其鍵的自然順序

我們不應該違反使用TreeMap通過值排序此規則排序 。

但是通過值進行排序,我們可以做到以下幾點:

  1. 使用Collection.sort的條目
  2. 插入排序項的排序創建的map
  3. 條目LinkedListLinkedHashMap:按照它們插入的順序保留鍵,這些鍵目前按自然順序排序。
  4. 返回LinkedHashMap作爲排序的map

    public static <K extends Comparable,V extends Comparable> Map<K,V> sortByValues(Map<K,V> map){ 
        List<Map.Entry<K,V>> entries = new LinkedList<Map.Entry<K,V>>(map.entrySet()); 
    
        Collections.sort(entries, new Comparator<Map.Entry<K,V>>() { 
    
         @Override 
         public int compare(Entry<K, V> o1, Entry<K, V> o2) { 
          return o1.getValue().compareTo(o2.getValue()); 
         } 
        }); 
    
    
        Map<K,V> sortedMap = new LinkedHashMap<K,V>(); 
    
        for(Map.Entry<K,V> entry: entries){ 
         sortedMap.put(entry.getKey(), entry.getValue()); 
        } 
    
        return sortedMap; 
    } 
    
    } 
    

參考:Sorting Map by value

+0

令人敬畏的代碼。真的把我很朦朧的東西放在一起。謝謝! – KodeSeeker

0

你在做什麼是真正的工具誤用。

我相信你需要做的是:

  1. 有輸入單詞的列表/陣列
  2. 創建映射到存儲字(尚精,你通過拆分輸入字符串得到它)作爲鍵值和頻率作爲值
  3. 收集唯一字,然後按頻率對收集庫進行排序
  4. 當您在輸出時,遍歷排序後的唯一字列表,獲取每個元素的頻率從frequencyMap中,輸出詞+頻率。

當然,你仍然可以使用像一個TreeSet和使用頻率爲重點,但你應該有話,因爲這地圖(又名多圖)的值的列表,而不是寫一個問題比較不遵守比較方的合同:http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html#compare%28T,%20T%29您的原始實施和其中一個答案的評論中的一個不符合sgn(compare(x, y)) == -sgn(compare(y, x)) for all x and y(原來的更糟)的規則。

一些代碼片段只是爲了給你提示:

List<String> words = ....; 
Map<String, Integer> wordFrequencyMap = new HashMap<String, Integer>(); 
// iterate words and update wordFrequencyMap accordingly 
List<String> uniqueWords = new ArrayList<String>(new HashSet<String>(words)); 
Collections.sort(uniqueWords, new WordFrequencyComparator<String>(wordFrequencyMap)); 
for (String w : uniqueWords) { 
    System.out.println("word : " + w + " frequency : " + wordFrequencyMap.get(w)); 
} 

缺少的部分不應該是什麼難的。