Monday, January 4, 2021

How to Sort Java HashMap

HashMap in Java calculates hash based on the key of the inserted (key, value) pair and store its elements according to that. So essentially HashMap is an unordered collection but you may come across a scenario when you want to sort HashMap in Java.

Sorting on HashMap can be done on either key or value, in this post we’ll see ways to sort HashMap in Java based on its keys or on its values.

Sorting HashMap on keys

If you have to sort HashMap on keys in Java, simplest option is to convert your HashMap to a TreeMap.

TreeMap is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time, depending on which constructor is used. If you want to sort HashMap according to the natural ordering of its keys you can use the following constructor of the TreeMap class.

TreeMap(Map<? extends K,? extends V> m)- Constructs a new tree map containing the same mappings as the given map, ordered according to the natural ordering of its keys.

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

public class SortMap {
  public static void main(String[] args) {
    // Creating HashMap
    Map<String, String> empMap = new HashMap<String, String>();
    // Storing elements
    empMap.put("E01", "Jack");
    empMap.put("E02", "Amy");
    empMap.put("E11", "Harvey");
    empMap.put("E45", "Mike");
    System.out.println("** Unsorted Map **");
    for(Map.Entry<String, String> emp : empMap.entrySet()) {
      System.out.println("Key- " + emp.getKey() + 
                  " Value- " + emp.getValue());
    }
       
    TreeMap<String, String> sortedEmpMap = new TreeMap<>(empMap);
    System.out.println("** Map sorted by keys **");
    for(Map.Entry<String, String> emp : sortedEmpMap.entrySet()) {
      System.out.println("Key- " + emp.getKey() + 
             " Value- " + emp.getValue());
    }
  }
}
Output
** Unsorted Map **
Key- E11 Value- Harvey
Key- E02 Value- Amy
Key- E01 Value- Jack
Key- E45 Value- Mike
** Map sorted by keys **
Key- E01 Value- Jack
Key- E02 Value- Amy
Key- E11 Value- Harvey
Key- E45 Value- Mike

Sorting HashMap on Values

For sorting Java HashMap on values you will have to convert HashMap to a Set and then sort that Set. For sorting a Set you have again two options convert that set to List or to a TreeSet.

If you just want the values of the Map in the sorted order then converting the values of the Map to a TreeSet is the simplest option.

public class SortMap {
  public static void main(String[] args) {
    // Creating HashMap
    Map<String, String> empMap = new HashMap<String, String>();
    // Storing elements
    empMap.put("E01", "Jack");
    empMap.put("E02", "Amy");
    empMap.put("E11", "Harvey");
    empMap.put("E45", "Mike");
    System.out.println("** Unsorted Map **");
    for(Map.Entry<String, String> emp : empMap.entrySet()) {
        System.out.println("Key- " + emp.getKey() + " Value- " + emp.getValue());
    }
    // Creating a TreeSet         
    Set<String> empSet = new TreeSet<String>(empMap.values());
    System.out.println("** Sorted Set **");
    for(String emp : empSet) {
      System.out.println(" Value- " + emp);
    }
  }
}
Output
** Unsorted Map **
Key- E11 Value- Harvey
Key- E02 Value- Amy
Key- E01 Value- Jack
Key- E45 Value- Mike
** Sorted Set **
 Value- Amy
 Value- Harvey
 Value- Jack
 Value- Mike

As you can see the values are sorted, only drawback is now you have a Set instead of a Map as you have only values stored now.

If you want a Map as end result of sorting a HashMap in Java then the process is a bit lengthy.

  1. Create a TreeSet specifying a Comparator for sorting.
  2. Convert the entry set of HashMap to a TreeSet by using addAll() method. At this step you have a sorted set containing the Map.entry elements.
  3. Create a LinkedHashMap to store the sorted values. LinkedHashMap is used here because it maintains insertion order.
  4. Iterate the TreeSet and put values in the created LinkedHashMap.
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

public class SortMap {
  public static void main(String[] args) {
    // Creating HashMap
    Map<String, String> empMap = new HashMap<String, String>();
    // Storing elements
    empMap.put("E01", "Jack");
    empMap.put("E02", "Amy");
    empMap.put("E11", "Harvey");
    empMap.put("E45", "Mike");
    System.out.println("** Unsorted Map **");
    for(Map.Entry<String, String> emp : empMap.entrySet()) {
      System.out.println("Key- " + emp.getKey() + " Value- " + emp.getValue());
    }
    // Creating a treeset with comparator
    Set<Map.Entry<String, String>> empSet = new TreeSet<Map.Entry<String, String>>(new EmpComparator());
    // Adding the entry set to a TreeSet
    empSet.addAll(empMap.entrySet());
    System.out.println("** Sorted Set **");
    for(Map.Entry<String, String> emp : empSet) {
      System.out.println("Key- " + emp.getKey() + " Value- " + emp.getValue());
    }
    // Using LinkedHashMap to maintain insertion order
    Map<String, String> sortedEmpMap = new LinkedHashMap<>();
    // Insert values in LinkedHashMap
    for(Map.Entry<String, String> emp : empSet) {
      sortedEmpMap.put(emp.getKey(), emp.getValue());
    }
    System.out.println("** Map Sorted by Values **");
    for(Map.Entry<String, String> emp : sortedEmpMap.entrySet()) {
      System.out.println("Key- " + emp.getKey() + " Value- " + emp.getValue());
    }
  }
}
// Comparator class
class EmpComparator implements Comparator<Map.Entry<String, String>>{
  @Override
  public int compare(Map.Entry<String, String> entry1, Map.Entry<String, String> entry2) {
    return entry1.getValue().compareTo(entry2.getValue());
  }    
}
Output
** Unsorted Map **
Key- E11 Value- Harvey
Key- E02 Value- Amy
Key- E01 Value- Jack
Key- E45 Value- Mike
** Sorted Set **
Key- E02 Value- Amy
Key- E11 Value- Harvey
Key- E01 Value- Jack
Key- E45 Value- Mike
** Map Sorted by Values **
Key- E02 Value- Amy
Key- E11 Value- Harvey
Key- E01 Value- Jack
Key- E45 Value- Mike

Rather than TreeSet you can also use an ArrayList to store Map.Entry elements. In that case you can use Collections.sort(list, new EmpComparator()) to sort on values.

That's all for the topic How to Sort Java HashMap. If something is missing or you have something to share about the topic please write a comment.


You may also like