简体   繁体   English

TreeMap 自定义比较器

[英]TreeMap Customized Comparator

So I want to use TreeMap with a customized comparator My key is a String: id, my value is an int: count;所以我想使用带有自定义比较器的 TreeMap 我的键是一个 String: id,我的值是一个 int: count; I NEED TO COMPARE THE COUNT, AS THE VALUE(INTEGER) IN THE TREEMAP So I have:我需要比较计数,作为 TREEMAP 中的值(整数)所以我有:

In one class:在一节课中:

import java.util.*;

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

In another class:在另一堂课中:

import java.util.Comparator;

public class SortIdCount implements Comparator<Integer>{

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

}

It shows error in eclipse:它在 Eclipse 中显示错误:

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

The type SortIdCount is not generic; SortIdCount 类型不是通用的; it cannot be parameterized with arguments < Integer >它不能用参数参数化<整数>

Reason : Class SortIdCount is not genric type so you can not pass parameterized argument.原因:类SortIdCount不是通用类型,因此您无法传递参数化参数。 Error At Line : (new SortIdCount<Integer>()行错误:( (new SortIdCount<Integer>()

Note : A TreeMap is always sorted based on its keys, however if you want to sort it based on its values then you can build a logic to do this using comparator.注意:TreeMap 总是根据其键进行排序,但是如果您想根据其值对其进行排序,那么您可以使用比较器构建一个逻辑来执行此操作。 Below is a complete code of sorting a TreeMap by values.以下是按值对 TreeMap 进行排序的完整代码。

To Sort on Values You can refer below code snippet.对值进行排序您可以参考以下代码片段。

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());
    }
  }
}

For more details refer this answer有关更多详细信息,请参阅此答案

As others might already have mentioned, that the Comparator used in the TreeMap constructor is used to sort the map by key .正如其他人可能已经提到的那样, TreeMap 构造函数中使用的Comparator用于按key对地图进行排序

public TreeMap(Comparator comparator) public TreeMap(比较器比较器)

... ordered according to the given comparator. ...根据给定的比较器排序。 All keys inserted into the map must be mutually comparable by the given comparator: comparator.compare(k1, k2) must not throw a ClassCastException for any keys k1 and k2 in the map...插入到映射中的所有必须通过给定的比较器相互比较:comparator.compare(k1, k2) 不能为映射中的任何键 k1 和 k2 抛出 ClassCastException...

But if you want to sort a map by the value , still we have a solution using LinkedHashMap as:但是如果你想按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);

Output:输出:

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

You can't have a TreeMap which sort by value.您不能拥有按值排序的TreeMap There are so many ways to sort a map by value but I believe TreeMap is not for that.按值对地图进行排序的方法有很多,但我相信 TreeMap 不适合那个。 If you look on the TreeMap constructor: TreeMap(Comparator<? super K> comparator) which takes comparator as an argument which's generic type clearly should be the super of Key of the Map .如果您查看 TreeMap 构造函数: TreeMap(Comparator<? super K> comparator)它将比较器作为参数,它的泛型类型显然应该是super of Key of the Mapsuper of Key of the Map So it impossible to send a Comparator<Integer> when the key is String .所以当键是String时,不可能发送Comparator<Integer>

Please follow the answer for sorting Map by value.请按照按值对 Map 进行排序的答案进行操作。

The comparator used for a TreeMap has to compare the keys, not the values.用于 TreeMap 的比较器必须比较键,而不是值。

So the comparison would have to take the passed key and look up the value in the map.因此,比较必须采用传递的键并在地图中查找值。 And there you have a classical hen (map) and egg (comparator) problem.你有一个经典的母鸡(地图)和鸡蛋(比较器)问题。 You need the comparator to create the map, but since the comparator has to look into the map, you need the map for the comparator.您需要比较器来创建地图,但由于比较器必须查看地图,因此您需要比较器的地图。 You could solve this by having comparator.setMap(map) after creation of the map.您可以通过在创建comparator.setMap(map)后使用comparator.setMap(map)来解决此问题。

But the most critical problem is, that your map will not work.但最关键的问题是,您的地图将无法使用。 As long as the entry is not written to the map, you don't have the value, so the comparator won't work.只要条目未写入地图,您就没有该值,因此比较器将无法工作。 Only idea I have for that is using two maps.我唯一的想法是使用两张地图。 Both String, Integer.字符串,整数。 The first one is simply used for the lookup in the comparator.第一个仅用于比较器中的查找。 So you always have to put into the first and then into the second.所以你总是必须先放入第一个,然后再放入第二个。

And then you still have problems, because you might easily violate the SortedMap contract.然后你仍然有问题,因为你可能很容易违反SortedMap契约。 A key must not change (regarding the sorting) after it is inserted into the map.将键插入映射后,不得更改(关于排序)。 But as soon as you put another value, you have a different sorting of the key.但是一旦你输入另一个值,你就会对键进行不同的排序。

So I'd really rethink your requirements and whether a TreeMap is the best solution to what you need.所以我真的会重新考虑您的要求以及 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