Sorting Java Map by Key & Value

How to sort a map by keys or values?

One of the most viewed java question on Stackoverflow is How to sort a Map<Key, Value> on the values in Java? Here I will try to re-code one of the solutions in a clearer way!

Objective:

  • Sort map by key and value.

Environment:

  • JVM

Library:

  • N/A

Order NOT Guaranteed

The most used type of map is HashMap which according to the official API page makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time“. Which means that the order in which we insert the data may not remain the same over time.

LinkedHashMap Maintains the Insertion-Order

While the order of the inserted data “EntrySet” can be maintained using LinkedHashMap “it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is normally the order in which keys were inserted into the map (insertion-order).“  it still does not provide a method or a way to sort the entries.

TreeMap is Sorted by Key

TreeMap by default sort the inserted entry by key, “The map is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time,” However, to sort the map by value we need a trick!

  • TreeMap has a constructor that accepts an object of type Comparator which is used to sort the map by keys.
  • The trick is to make this comparator able to get access to values instead of keys.
  • So, we will pass the map to the comparator which will allow us to return values by using map.get(key).
  • Notice that values should be of type Comparable i.e. values object should implement Comparable interface. Here in this example values are of type String which is by default of type Comparable.
package com.hmkcode;

import java.util.Map;
import java.util.TreeMap;

public class MapSort {

  public static Map sortByValue(Map unsortedMap){
  	Map sortedMap = new TreeMap(new ValueComparator(unsortedMap));
  	sortedMap.putAll(unsortedMap);
  	return sortedMap;
  }
  public static Map sortByKey(Map unsortedMap){
  	Map sortedMap = new TreeMap();
  	sortedMap.putAll(unsortedMap);
  	return sortedMap;
  }
}
package com.hmkcode;

import java.util.Comparator;
import java.util.Map;

public class ValueComparator implements Comparator {

  Map map;

  public ValueComparator(Map map){
  	this.map = map;
  }
  public int compare(Object keyA, Object keyB){

  	Comparable valueA = (Comparable) map.get(keyA);
  	Comparable valueB = (Comparable) map.get(keyB);

  	System.out.println(valueA +" - "+valueB);

  	return valueA.compareTo(valueB);

  }
}
package com.hmkcode;

import java.util.HashMap;
import java.util.Map;

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

  	Map map = new HashMap();

  	//*value Class should implements the Comparable interface
  	//*String implements Comparable by default.

  	map.put("Z", "3");
  	map.put("D", "4");
  	map.put("A", "1");
  	map.put("B", "2");
  	map.put("F", "6");
  	map.put("E", "5");

  	System.out.println("Unsorted Map: "+map);
  	System.out.println("Sorted Map By Values: "+MapSort.sortByValue(map));
  	System.out.println("Sorted Map By Keys: "+MapSort.sortByKey(map));

  }
}