Java TreeMap比较器

37

我需要为TreeMap编写一个比较器。 我应该在TreeMap的构造函数中匿名编写它吗?还有其他什么方法可以编写我的比较器。 目前,Java不喜欢我的代码(我可以匿名地这样做吗?):

SortedMap<String, Double> myMap = 
    new TreeMap<String, Double>(new Comparator<Entry<String, Double>>()
    {
        public int compare(Entry<String, Double> o1, Entry<String, Double> o2)
        {
            return o1.getValue().compareTo(o2.getValue());
        } 
    });
  1. 我能以匿名方式执行上述操作吗?
  2. 还有其他方法可以完成这个任务吗?
  3. 我想按值(Value)而不是键(Key)对myMap进行排序。

TreeMap的比较器签名仅限于键。例如:new Comparator() { @Override public int compare(String a, String b) { return 0; } - figaro
3个回答

73

无法根据值对 TreeMap 进行排序。

一种基于红黑树的导航映射实现。该映射按其键的自然排序进行排序,或者根据在创建映射时提供的比较器进行排序,具体取决于使用哪个构造函数。 您需要为 Comparator<? super K> 提供比较器 comparator,以便比较键。

要根据值提供排序,您将需要使用SortedSet。使用

SortedSet<Map.Entry<String, Double>> sortedset = new TreeSet<Map.Entry<String, Double>>(
            new Comparator<Map.Entry<String, Double>>() {
                @Override
                public int compare(Map.Entry<String, Double> e1,
                        Map.Entry<String, Double> e2) {
                    return e1.getValue().compareTo(e2.getValue());
                }
            });

  sortedset.addAll(myMap.entrySet());

为了给你举一个例子

    SortedMap<String, Double> myMap = new TreeMap<String, Double>();
    myMap.put("a", 10.0);
    myMap.put("b", 9.0);
    myMap.put("c", 11.0);
    myMap.put("d", 2.0);
    sortedset.addAll(myMap.entrySet());
    System.out.println(sortedset);

输出:

  [d=2.0, b=9.0, a=10.0, c=11.0]

我该如何逐个向myMap添加元素?myMap.add(Map.Entry<String, Double> new Map.Entry<String, Double>(vStr, cur)); - CodeKingPlusPlus
@CodeKingPlusPlus 不是的,你只使用put方法。请查看添加的示例。将值放入Map中后,使用SortedSet对值进行排序。 - Amit Deshpande
1
这个可以运行,但会删除重复的值。但我想要保留列表中的重复值。有人可以帮我吗? - Priyanka Alachiya
即使您对元素进行排序,当您将它们放回TreeMap时,顺序仍由键比较器/自然顺序决定。相反,您可以将有序条目插入到LinkedHashmap中,以至少返回一个元素的有序映射视图。 - WesternGun
1
@PriyankaAlachiya 使用 ArrayList 而不是 Set。将 Map 的元素添加到列表中,并在 Collections.sort() 中传入比较器。对我有用。另外,我在解决 leetcode 上的“前 K 个高频元素”问题时也使用了这种技巧。 - cs-dev

18

比较器应该只针对键而不是整个条目。它基于键对条目进行排序。

您应将其更改为以下内容

SortedMap<String, Double> myMap = 
    new TreeMap<String, Double>(new Comparator<String>()
    {
        public int compare(String o1, String o2)
        {
            return o1.compareTo(o2);
        } 
});

更新

您可以按以下步骤操作(创建映射中的条目列表并根据值对列表进行排序,但请注意,这不会对映射本身进行排序) -

List<Map.Entry<String, Double>> entryList = new ArrayList<Map.Entry<String, Double>>(myMap.entrySet());
    Collections.sort(entryList, new Comparator<Map.Entry<String, Double>>() {
        @Override
        public int compare(Entry<String, Double> o1, Entry<String, Double> o2) {
            return o1.getValue().compareTo(o2.getValue());
        }
    });

@CodeKingPlusPlus:你不能根据值对地图本身进行排序。但是你可以获取条目列表并对其进行排序。但是这样做可能没有使用TreeMap的意义,除非你交换键和值。 - Bhesh Gurung

0

你可以轻松地交换键和值。例如:

        String[] k = {"Elena", "Thomas", "Hamilton", "Suzie", "Phil"};
        int[] v = {341, 273, 278, 329, 445};
        TreeMap<Integer,String>a=new TreeMap();
        for (int i = 0; i < k.length; i++) 
           a.put(v[i],k[i]);            
        System.out.println(a.firstEntry().getValue()+"\t"+a.firstEntry().getKey());
        a.remove(a.firstEntry().getKey());
        System.out.println(a.firstEntry().getValue()+"\t"+a.firstEntry().getKey());

1
这是在尝试解决最后一个问题,而不是前两个。 - Juan Carlos Mendoza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接