TreeMap 按值排序 [英] TreeMap sort by value

查看:37
本文介绍了TreeMap 按值排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想编写一个比较器,让我可以按值而不是默认的自然顺序对 TreeMap 进行排序.

I want to write a comparator that will let me sort a TreeMap by value instead of the default natural ordering.

我尝试过类似的操作,但无法找出问题所在:

I tried something like this, but can't find out what went wrong:

import java.util.*;

class treeMap {
    public static void main(String[] args) {
        System.out.println("the main");
        byValue cmp = new byValue();
        Map<String, Integer> map = new TreeMap<String, Integer>(cmp);
        map.put("de",10);
        map.put("ab", 20);
        map.put("a",5);

        for (Map.Entry<String,Integer> pair: map.entrySet()) {
            System.out.println(pair.getKey()+":"+pair.getValue());
        }
    }
}

class byValue implements Comparator<Map.Entry<String,Integer>> {
    public int compare(Map.Entry<String,Integer> e1, Map.Entry<String,Integer> e2) {
        if (e1.getValue() < e2.getValue()){
            return 1;
        } else if (e1.getValue() == e2.getValue()) {
            return 0;
        } else {
            return -1;
        }
    }
}

我想我要问的是:我可以将 Map.Entry 传递给比较器吗?

I guess what am I asking is: Can I get a Map.Entry passed to the comparator?

推荐答案

你不能让 TreeMap 本身对值进行排序,因为这违背了 SortedMap 规范:

You can't have the TreeMap itself sort on the values, since that defies the SortedMap specification:

一个Map,它进一步在其上提供总排序.

A Map that further provides a total ordering on its keys.

但是,使用外部集合,您始终可以对 Map.entrySet() 随心所欲,可以通过键、值,甚至是两者的组合(!!).

However, using an external collection, you can always sort Map.entrySet() however you wish, either by keys, values, or even a combination(!!) of the two.

这是一个返回 Map.EntrySortedSet 的通用方法,给定一个 Map,其值为 Comparable>:

Here's a generic method that returns a SortedSet of Map.Entry, given a Map whose values are Comparable:

static <K,V extends Comparable<? super V>>
SortedSet<Map.Entry<K,V>> entriesSortedByValues(Map<K,V> map) {
    SortedSet<Map.Entry<K,V>> sortedEntries = new TreeSet<Map.Entry<K,V>>(
        new Comparator<Map.Entry<K,V>>() {
            @Override public int compare(Map.Entry<K,V> e1, Map.Entry<K,V> e2) {
                int res = e1.getValue().compareTo(e2.getValue());
                return res != 0 ? res : 1;
            }
        }
    );
    sortedEntries.addAll(map.entrySet());
    return sortedEntries;
}

现在您可以执行以下操作:

Now you can do the following:

    Map<String,Integer> map = new TreeMap<String,Integer>();
    map.put("A", 3);
    map.put("B", 2);
    map.put("C", 1);   

    System.out.println(map);
    // prints "{A=3, B=2, C=1}"
    System.out.println(entriesSortedByValues(map));
    // prints "[C=1, B=2, A=3]"

请注意,如果您尝试修改 SortedSet 本身或其中的 Map.Entry,将会发生一些奇怪的事情,因为这不再是像 entrySet() 这样的原始地图是.

Note that funky stuff will happen if you try to modify either the SortedSet itself, or the Map.Entry within, because this is no longer a "view" of the original map like entrySet() is.

一般来说,按值对地图条目进行排序的需求是非典型的.

Generally speaking, the need to sort a map's entries by its values is atypical.

您的原始比较器使用 == 比较 Integer.这几乎总是错误的,因为带有 Integer 操作数的 == 是引用相等,而不是值相等.

Your original comparator compares Integer using ==. This is almost always wrong, since == with Integer operands is a reference equality, not value equality.

    System.out.println(new Integer(0) == new Integer(0)); // prints "false"!!!

相关问题

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆