TreeMap sort by value

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

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

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.

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]"

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.


Note on == for 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"!!!

Related questions

  • When comparing two Integers in Java does auto-unboxing occur? (NO!!!)
  • Is it guaranteed that new Integer(i) == i in Java? (YES!!!)

Leave a Comment

tech