簡體   English   中英

使用TreeMap和Comparator按值對HashMap進行排序

[英]Sorting HashMap by value using a TreeMap and Comparator

我使用以下代碼創建一個哈希圖,然后使用樹圖和比較器對哈希圖中的值進行排序。 但是,輸出是相當意外的。 因此,任何關於我做錯事的想法都會有所幫助

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

請檢查的JavaDoc的compare :你不回更大的價值,但-1o1 < o20o1 = o21o1 > o2 所以你可以這樣寫:

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

TreeMapJava文檔明確指出:

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

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

但是,要按值排序,我們可以執行以下操作:

  1. 創建map條目的LinkedList
  2. 使用Collection.sort對條目進行排序
  3. 將排序后的條目插入LinkedHashMap :保持鍵的插入順序,當前是按自然順序排序的。
  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; } } 

參考: 按值對地圖排序

您在做什么實際上是濫用工具。

我相信您需要做的是:

  1. 具有輸入單詞的列表/數組(仍然可以通過分割輸入字符串來獲得它)
  2. 創建一個映射以將單詞存儲為鍵,將頻率存儲為值
  3. 收集唯一的單詞,然后根據頻率對收集的單詞進行排序
  4. 在執行輸出時,遍歷每個元素的排序后的唯一詞列表,從frequencyMap獲取頻率,然后輸出詞+頻率。

當然,您仍然可以使用TreeSet之類的東西,並使用頻率作為鍵,但是您應該使用單詞列表作為此映射的值(也稱為Multi-Map),而不是編寫不遵循合同的有問題的比較器比較器: 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答案均不符合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));
}

缺少的部分應該沒有什么困難。

暫無
暫無

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

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