简体   繁体   English

按值排序HashMaps

[英]Sorting HashMaps by value

When I need to sort a HashMap by value, the advice seems to be to create the HashMap and then put the data into a TreeMap which is sorted by value. 当我需要按值对HashMap进行排序时,建议似乎是创建HashMap,然后将数据放入按值排序的TreeMap中。

For example: Sort a Map<Key, Value> by values (Java) 例如: 按值(Java)对Map <Key,Value>进行排序

My question: why is it necessary to do this? 我的问题:为什么有必要这样做? Why not create a TreeMap(which is sorted by keys) and then sort it in place by value? 为什么不创建一个TreeMap(按键排序),然后按值对其进行排序?

Because you can't reorder the entries of a TreeMap manually. 因为您无法手动重新排序TreeMap的条目。 TreeMap entries are always sorted on the keys. TreeMap条目始终按键排序。

I'm going to throw out Map that could be iterated in the order of values as another answer to "How to do it," though...specifically, a solution which doesn't return a map that chokes (by throwing exceptions) on queries to keys not in your original map. 我将丢弃可以按值的顺序迭代的Map作为“如何做到”的另一个答案,但是......具体来说,这个解决方案不会返回阻塞的地图(通过抛出异常)查询不在原始地图中的键。

If you know your values to be unique, you can use Guava's BiMap (bidirectional map) to store the data. 如果您知道您的值是唯一的,则可以使用Guava的BiMap (双向映射)来存储数据。 Create a HashBiMap as you would your HashMap , then create a new TreeMap from its inverse: HashMap一样创建HashBiMap ,然后从其反向创建一个新的TreeMap

new TreeMap<>(biMap.inverse());

That map will then be sorted by the values. 然后,该地图将按值排序。 Remember that what you're thinking of as "keys" and "values" will be swapped. 请记住,您所想的“键”和“值”将被交换。

If your values are not unique, you can create a multimap of the inverse. 如果您的值不是唯一的,则可以创建反向的多图。 A multimap is essentially a mapping from each key to one or more values. multimap实质上是从每个键到一个或多个值的映射。 It's usually implemented by making a map from a key to a list. 它通常通过制作从键到列表的映射来实现。 You don't have to do that though, because Google did it for you. 你不必这样做,因为谷歌为你做了。 Just create a multimap from your existing map, and ask Guava to invert it for you into a TreeMultimap , which, as you can guess, is a TreeMap that can hold multiple values per key. 只需从现有地图创建一个多图,然后让Guava将它反转为TreeMultimap ,您可以猜测,这是一个可以为每个键保存多个值的TreeMap

Multimaps.invertFrom(Multimaps.forMap(myMap), new TreeMultimap<V, K>());

Multimap documentation is provided. 提供了Multimap文档。

I have this very small code which is working fine: 我有这个非常小的代码,工作正常:

public class SortMapByValues {
    public static void main(String[] args) {

        Map<Integer, String> myMap = new LinkedHashMap<Integer, String>();

        myMap.put(100, "hundread");
        myMap.put(500, "fivehundread");
        myMap.put(250, "twofifty");
        myMap.put(300, "threehundread");
        myMap.put(350, "threefifty");
        myMap.put(400, "fourhundread");

        myMap = sortMapByValues(myMap);

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

    }

    public static Map<Integer, String> sortMapByValues(
            Map<Integer, String> firstMap) {
        Map<String, Integer> SecondyMap = new TreeMap<String, Integer>();

        for (Map.Entry<Integer, String> entry : firstMap.entrySet()) {
            SecondyMap.put(entry.getValue(), entry.getKey());
        }
        firstMap.clear();
        for (Map.Entry<String, Integer> entry : SecondyMap.entrySet()) {
            firstMap.put(entry.getValue(), entry.getKey());
        }
        return firstMap;
    }

}

Output: 输出:

500 fivehundread  
400 fourhundread  
100 hundread  
350 threefifty  
300 threehundread  
250 twofifty 

I wrote the following one-liner using Java 8 Stream API to sort any given map by value: 我使用Java 8 Stream API编写了以下单行代码,按值对任何给定的地图进行排序:

List<Map.Entry<String, String>> sortedEntries = map.entrySet().stream()
  .sorted((o1, o2) -> o1.getValue().compareTo(o2.getValue())).collect(Collectors.toList());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM