Sorting a map by values

14 Feb 2013 | java, hibernate

How to sort a map in Java by its values instead of by its keys.

Most applications of Maps do not require ordering. Occasionally, we stumble upon instances where maps need sorting. To maintain insertion order in Maps, use a LinkedHashMap. To sort on the keys, use a SortedMap.

However, once every thousand years or so, the planets align and we need to sort a map by its values. For these situations, some people prefer to create a List of Map entries (List<Map.Entry<K,V» and then sort using Collections.sort() with a custom Comparator. That works if you don’t need the output as a map. Yes, you can put all the list entries into a map, but let’s assume that the fundamental reason you’re here is that you’re too lazy to write all that code every time you have to sort a map.

A simpler way of sorting a map’s values is to use a SortedMap that sorts a map using a Comparator to compare the Map’s values. The only restriction you have is that the values must implement Comparable – not a sin in our world. Here’s the code…

/**
* Utility to sort a map by values.
*
* @return {@link TreeMap} map sorted by its values
* @throws {@link NullPointerException} if one of the values in the map is
*         null.
*/
public static <K, V extends Comparable<V>> Map<K, V> sortByValue(Map<K, V> unsortedMap) {
  Map<K, V> sortedMap = new TreeMap<K, V>(new ValueComparator<K, V>(unsortedMap));
  sortedMap.putAll(unsortedMap);
  return sortedMap;
}

static class ValueComparator<K, V extends Comparable<V>> implements Comparator<K> {
  private Map<K, V> innerMap;

  private ValueComparator(Map<K, V> innerMap) {
  this.innerMap = innerMap;
}

  @Override
  public int compare(K o1, K o2) {
    V value1 = innerMap.get(o1);
    V value2 = innerMap.get(o2);

  /*
  * If the values are equal, return 1.
  * This is because the sortedMap thinks
  * it's comparing keys and replaces the
  * existing value of the key with the new
  * one if the comparator says they're equal.
  */
  return (value1.compareTo(value2) == 0) ? 1 : value1.compareTo(value2);
  }
}
comments powered by Disqus

Newer · View Archive (8)

Why ORM?

Why use ORM?

The path to coding Nirvana is a long one. As you navigate these treacherous ways, you’ll find many corpses – of people who have died of SQL over-injection or of Object-Relational-Miscarriage. For those of you who’ve been doing object-relational stuff long enough and have scars in unmentionable places, go back to your drinks. For the rest of you, for whom ‘Why ORM?’ is an interview question, gather around and warm your toes by the electric light.