簡體   English   中英

TreeMap 自定義比較器

[英]TreeMap Customized Comparator

所以我想使用帶有自定義比較器的 TreeMap 我的鍵是一個 String: id,我的值是一個 int: count; 我需要比較計數,作為 TREEMAP 中的值(整數)所以我有:

在一節課中:

import java.util.*;

public TreeMap<String, Integer> tm = new TreeMap<String, Integer>(new SortIdCount<Integer>());

在另一堂課中:

import java.util.Comparator;

public class SortIdCount implements Comparator<Integer>{

    public int compare(Integer count1, Integer count2) {
        return count1.compareTo(count2);
    }

}

它在 Eclipse 中顯示錯誤:

The type SortIdCount is not generic; it cannot be parameterized with arguments <Integer>

SortIdCount 類型不是通用的; 它不能用參數參數化<整數>

原因:類SortIdCount不是通用類型,因此您無法傳遞參數化參數。 行錯誤:( (new SortIdCount<Integer>()

注意:TreeMap 總是根據其鍵進行排序,但是如果您想根據其值對其進行排序,那么您可以使用比較器構建一個邏輯來執行此操作。 以下是按值對 TreeMap 進行排序的完整代碼。

對值進行排序您可以參考以下代碼片段。

import java.util.*;

public class TreeMapDemo {
  //Method for sorting the TreeMap based on values
  public static <K, V extends Comparable<V>> Map<K, V> 
    sortByValues(final Map<K, V> map) {
    Comparator<K> valueComparator = 
             new Comparator<K>() {
      public int compare(K k1, K k2) {
        int compare = 
              map.get(k1).compareTo(map.get(k2));
        if (compare == 0) 
          return 1;
        else 
          return compare;
      }
    };

    Map<K, V> sortedByValues = 
      new TreeMap<>(valueComparator);
    sortedByValues.putAll(map);
    return sortedByValues;
  }
  public static void main(String args[]) {

    TreeMap<String, Integer> treemap = new TreeMap<>();

    // Put elements to the map
    treemap.put("Key1", 5);
    treemap.put("Key2", 4);
    treemap.put("Key3", 3);
    treemap.put("Key4", 2);
    treemap.put("Key5", 1);

    // Calling the method sortByvalues
    Map sortedMap = sortByValues(treemap);

    // Get a set of the entries on the sorted map
    Set set = sortedMap.entrySet();

    // Get an iterator
    Iterator i = set.iterator();

    // Display elements
    while(i.hasNext()) {
      Map.Entry me = (Map.Entry)i.next();
      System.out.print(me.getKey() + ": ");
      System.out.println(me.getValue());
    }
  }
}

有關更多詳細信息,請參閱此答案

正如其他人可能已經提到的那樣, TreeMap 構造函數中使用的Comparator用於按key對地圖進行排序

public TreeMap(比較器比較器)

...根據給定的比較器排序。 插入到映射中的所有必須通過給定的比較器相互比較:comparator.compare(k1, k2) 不能為映射中的任何鍵 k1 和 k2 拋出 ClassCastException...

但是如果你想按value對地圖進行排序,我們仍然有一個使用LinkedHashMap的解決方案:

    Map<String, Integer> treeMap = new TreeMap<>();
    treeMap.put("hi", 1);
    treeMap.put("there", 3);
    treeMap.put("hey", 2);
    treeMap = treeMap.entrySet().stream().sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldV, newV) -> oldV, LinkedHashMap::new));
    System.out.println(treeMap);

輸出:

{there=3, hey=2, hi=1}

您不能擁有按值排序的TreeMap 按值對地圖進行排序的方法有很多,但我相信 TreeMap 不適合那個。 如果您查看 TreeMap 構造函數: TreeMap(Comparator<? super K> comparator)它將比較器作為參數,它的泛型類型顯然應該是super of Key of the Mapsuper of Key of the Map 所以當鍵是String時,不可能發送Comparator<Integer>

請按照按值對 Map 進行排序的答案進行操作。

用於 TreeMap 的比較器必須比較鍵,而不是值。

因此,比較必須采用傳遞的鍵並在地圖中查找值。 你有一個經典的母雞(地圖)和雞蛋(比較器)問題。 您需要比較器來創建地圖,但由於比較器必須查看地圖,因此您需要比較器的地圖。 您可以通過在創建comparator.setMap(map)后使用comparator.setMap(map)來解決此問題。

但最關鍵的問題是,您的地圖將無法使用。 只要條目未寫入地圖,您就沒有該值,因此比較器將無法工作。 我唯一的想法是使用兩張地圖。 字符串,整數。 第一個僅用於比較器中的查找。 所以你總是必須先放入第一個,然后再放入第二個。

然后你仍然有問題,因為你可能很容易違反SortedMap契約。 將鍵插入映射后,不得更改(關於排序)。 但是一旦你輸入另一個值,你就會對鍵進行不同的排序。

所以我真的會重新考慮您的要求以及 TreeMap 是否是您需要的最佳解決方案。

public class SortIdCount implements Comparator<String> {

    public int compare(String count1, String count2) {
        return count1.compareTo(count2);
    }
}

暫無
暫無

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

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