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

Older · View Archive (17)

What's with the Lokpal?

Lying in bed with a fever-addled brain and nothing to do, the idling grey matter turns to an incident at work yesterday. Friends and countrymen in the city rushing to form a human chain against corruption - that poisoned, vile spear thrust deeper into us over the years by corrupt politicians and the bureaucracy; two shaky pillars of our tripod-mounted democracy. So above-mentioned friends were running off to form a human chain. I politely declined to join, having to complete labours for my masters in a land far to the west.

Newer

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.