January 4, 2024

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 using TreeMap, TreeSet and by using Java Stream API.

1. 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

2. 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.

3. Sorting HashMap Using Java Stream API

You can use sorted() method of the Java Stream API to sort a Map either by key or by value. As a Comparator argument to the sorted() method pass Map.entry.comparingByKey() to sort by key and Map.Entry.comparingByValue() to sort by value.

Collect the resulting stream after sorting to a Map using Collectors.toMap(), also pass LinkedHashMap::new as one of the argument to the Collectors.toMap() so that ordering (which you get after sorting) is maintained.

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

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());
      }
      // Sorting Map by key using Map.Entry.comparingByKey()
      Map<String, String> sortedEmpMapKey = empMap.entrySet()
          .stream()
          .sorted(Map.Entry.comparingByKey())
          .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue(), (e1, e2)->e2, LinkedHashMap::new));
      
      System.out.println("** Sorted Map By Key **");
      for(Map.Entry<String, String> emp : sortedEmpMapKey.entrySet()) {
        System.out.println("Key- " + emp.getKey() + " Value- " + emp.getValue());
      }
      
      // Sorting Map by value using Map.Entry.comparingByValue()
      Map<String, String> sortedEmpMapValue = empMap.entrySet()
            .stream()
            .sorted(Map.Entry.comparingByValue())
            .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue(), (e1, e2)->e2, LinkedHashMap::new));
        
      System.out.println("** Sorted Map By Value **");
      for(Map.Entry<String, String> emp : sortedEmpMapValue.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
** Sorted Map By Key **
Key- E01 Value- Jack
Key- E02 Value- Amy
Key- E11 Value- Harvey
Key- E45 Value- Mike
** Sorted Map By Value **
Key- E02 Value- Amy
Key- E11 Value- Harvey
Key- E01 Value- Jack
Key- E45 Value- Mike

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

No comments:

Post a Comment