Saturday, August 14, 2021

How to Sort a HashMap in Java

In this post we’ll see how to sort a HashMap in Java which is by design an unordered collection.

You can sort a HashMap on either the keys or the values. You can also use Java Stream API, Java 8 onward to sort a HashMap. So, let’s see example code to sort HashMap in Java on keys as well as values.


Sorting HashMap using keys

If you want to sort a HashMap on keys, just convert HashMap to TreeMap. TreeMap is sorted according to the natural ordering of its keys so just construct a TreeMap by passing your HashMap. Constructor used is this one-

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.

If you want to sort HashMap in different order than the natural ordering then you need to pass a comparator. In that case you can use the following constructor.

TreeMap(Comparator<? super K> comparator)- Constructs a new, empty tree map, ordered according to the given comparator.

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

public class HashMapSorting {

  public static void main(String[] args) {
    Map<String, String> langMap = new HashMap<String, String>();
    langMap.put("ENG", "English");
    langMap.put("NLD", "Dutch");
    langMap.put("ZHO", "Chinese");
    langMap.put("BEN", "Bengali");
    langMap.put("ZUL", "Zulu");
    System.out.println("-- Original Map --");
    for(Map.Entry<String, String> lang : langMap.entrySet()) {
      System.out.println("Key- " + lang.getKey() + 
                    " Value- " + lang.getValue());
    }
    TreeMap<String, String> sortedLangMap = new TreeMap<String, String>(langMap);
    System.out.println("-- Sorted by keys Map--");
    for(Map.Entry<String, String> lang : sortedLangMap.entrySet()) {
      System.out.println("Key- " + lang.getKey() + 
            " Value- " + lang.getValue());
    }
  }
}

Output

-- Original Map --
Key- ZHO Value- Chinese
Key- ZUL Value- Zulu
Key- NLD Value- Dutch
Key- BEN Value- Bengali
Key- ENG Value- English
-- Sorted by keys Map--
Key- BEN Value- Bengali
Key- ENG Value- English
Key- NLD Value- Dutch
Key- ZHO Value- Chinese
Key- ZUL Value- Zulu

Sorting HashMap using keys in descending order

If you want HashMap sorting done in descending order then you can pass a Comparator while constructing TreeMap.

public class HashMapSorting {

  public static void main(String[] args) {
    Map<String, String> langMap = new HashMap<String, String>();
    langMap.put("ENG", "English");
    langMap.put("NLD", "Dutch");
    langMap.put("ZHO", "Chinese");
    langMap.put("BEN", "Bengali");
    langMap.put("ZUL", "Zulu");
    System.out.println("-- Original Map --");
    for(Map.Entry<String, String> lang : langMap.entrySet()) {
      System.out.println("Key- " + lang.getKey() + 
                    " Value- " + lang.getValue());
    }
    // TreeMap with Comparator
    TreeMap<String, String> sortedLangMap = new TreeMap<String, String>(new Comparator<String>() {
      @Override
      public int compare(String str1, String str2) {
        return str2.compareTo(str1);
      }  
    });
    // Adding HashMap entries to TreeMap
    sortedLangMap.putAll(langMap);
    System.out.println("-- Keys of the Map sorted in descending order --");
    for(Map.Entry<String, String> lang : sortedLangMap.entrySet()) {
      System.out.println("Key- " + lang.getKey() + 
            " Value- " + lang.getValue());
    }
  }
}

Output

-- Original Map --
Key- ZHO Value- Chinese
Key- ZUL Value- Zulu
Key- NLD Value- Dutch
Key- BEN Value- Bengali
Key- ENG Value- English
-- keys of the Map sorted in descending order --
Key- ZUL Value- Zulu
Key- ZHO Value- Chinese
Key- NLD Value- Dutch
Key- ENG Value- English
Key- BEN Value- Bengali

Sorting HashMap using Values

If you have to sort HashMap in Java on values then you will have to convert your HashMap to List or Set having Map.Entry values and then sort that List or Set. Then you will have to add values back to a LinkedHashMap as insertion order is maintained in LinkedHashMap.

If you just want the values in sorted order not the (key, value) pair then you can convert the values view of the Map to TreeSet. That will give you values in sorted order as per the natural ordering.

public class HashMapSorting {

  public static void main(String[] args) {
    Map<String, String> langMap = new HashMap<String, String>();
    langMap.put("ENG", "English");
    langMap.put("NLD", "Dutch");
    langMap.put("ZHO", "Chinese");
    langMap.put("BEN", "Bengali");
    langMap.put("ZUL", "Zulu");
    System.out.println("-- Original Map --");
    for(Map.Entry<String, String> lang : langMap.entrySet()) {
      System.out.println("Key- " + lang.getKey() + 
                    " Value- " + lang.getValue());
    }
    TreeSet<String> valueSet = new TreeSet<>(langMap.values());
    System.out.println("-- Sorted HashMap Values --");
    for(String str : valueSet) {
      System.out.println(" Value- " + str);
    }
  }
}

Output

-- Original Map --
Key- ZHO Value- Chinese
Key- ZUL Value- Zulu
Key- NLD Value- Dutch
Key- BEN Value- Bengali
Key- ENG Value- English
-- Sorted HashMap Values --
 Value- Bengali
 Value- Chinese
 Value- Dutch
 Value- English
 Value- Zulu

If you want a sorted Map then as I said you need to convert HashMap to List or Set and then sort it. After that put values back in a LinkedHashMap. In this example Set is used.

import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeSet;

public class HashMapSorting {

  public static void main(String[] args) {
    Map<String, String> langMap = new HashMap<String, String>();
    langMap.put("ENG", "English");
    langMap.put("NLD", "Dutch");
    langMap.put("ZHO", "Chinese");
    langMap.put("BEN", "Bengali");
    langMap.put("ZUL", "Zulu");
    System.out.println("-- Original Map --");
    for(Map.Entry<String, String> lang : langMap.entrySet()) {
      System.out.println("Key- " + lang.getKey() + 
                    " Value- " + lang.getValue());
    }
    // Creating TreeSet with a comparator
    TreeSet<Map.Entry<String, String>> langSet = new TreeSet<Map.Entry<String, String>>(
      new Comparator<Map.Entry<String, String>>(){
        @Override
        public int compare(Entry<String, String> entry1,
            Entry<String, String> entry2) {
          return entry1.getValue().compareTo(entry2.getValue());
        }          
      });
    // Adding Map.entrySet to TreeSet
    langSet.addAll(langMap.entrySet());
    
    Map<String, String> newMap = new LinkedHashMap<String, String>();
    // Insert values in LinkedHashMap
    for(Map.Entry<String, String> entry : langSet) {
      newMap.put(entry.getKey(), entry.getValue());
    }
    System.out.println("-- Sorted Map(by Value) --");
    for(Map.Entry<String, String> lang : newMap.entrySet()) {
      System.out.println("Key- " + lang.getKey() + " Value- " + lang.getValue());
    }
  }
}

If you want to use List to sort a HashMap by values then you can use the following Java code.

public class HashMapSorting {

  public static void main(String[] args) {
    Map<String, String> langMap = new HashMap<String, String>();
    langMap.put("ENG", "English");
    langMap.put("NLD", "Dutch");
    langMap.put("ZHO", "Chinese");
    langMap.put("BEN", "Bengali");
    langMap.put("ZUL", "Zulu");
    System.out.println("-- Original Map --");
    for(Map.Entry<String, String> lang : langMap.entrySet()) {
      System.out.println("Key- " + lang.getKey() + 
                    " Value- " + lang.getValue());
    }
    // creating list
    List<Map.Entry<String, String>> newList = new ArrayList<Map.Entry<String, String>>(langMap.entrySet());
    // sorting list
    Collections.sort(newList, new Comparator<Map.Entry<String, String>>(){
      @Override
      public int compare(Entry<String, String> entry1,
            Entry<String, String> entry2) {
        return entry1.getValue().compareTo(entry2.getValue());
      }
        
    });
    
    Map<String, String> newMap = new LinkedHashMap<String, String>();
    // Insert values in LinkedHashMap
    for(Map.Entry<String, String> entry : newList) {
      newMap.put(entry.getKey(), entry.getValue());
    }
    System.out.println("-- Sorted Map(by Value) --");
    for(Map.Entry<String, String> lang : newMap.entrySet()) {
      System.out.println("Key- " + lang.getKey() + " Value- " + lang.getValue());
    }
  }
}

Output

-- Original Map --
Key- ZHO Value- Chinese
Key- ZUL Value- Zulu
Key- NLD Value- Dutch
Key- BEN Value- Bengali
Key- ENG Value- English
-- Sorted Map(by Value) --
Key- BEN Value- Bengali
Key- ZHO Value- Chinese
Key- NLD Value- Dutch
Key- ENG Value- English
Key- ZUL Value- Zulu

Sorting HashMap using Java stream

Using Stream API Java 8 onward you can sort a HashMap with very few lines. Java stream API has a sorted method that can be used to sort the elements in the stream, then you can collect it in a LinkedHashMap. Why LinkedHahsMap? To retain the order you get after applying the sorted method.

public class HashMapSorting {

  public static void main(String[] args) {
    Map langMap = new HashMap();
    langMap.put("ENG", "English");
    langMap.put("NLD", "Dutch");
    langMap.put("ZHO", "Chinese");
    langMap.put("BEN", "Bengali");
    langMap.put("ZUL", "Zulu");
    System.out.println("-- Original Map --");
    for(Map.Entry lang : langMap.entrySet()) {
      System.out.println("Key- " + lang.getKey() + 
                      " Value- " + lang.getValue());
    }
    Map newMap = langMap.entrySet().stream().sorted(Map.Entry.comparingByValue())
                                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (k,v)->k,LinkedHashMap::new));
    System.out.println("-- Sorted Map --");
    newMap.entrySet().forEach((e)->{System.out.println("Key- " + e.getKey() + " Value- " + e.getValue());});
  }
}

Output

-- Original Map --
Key- ZHO Value- Chinese
Key- ZUL Value- Zulu
Key- NLD Value- Dutch
Key- BEN Value- Bengali
Key- ENG Value- English
-- Sorted Map --
Key- BEN Value- Bengali
Key- ZHO Value- Chinese
Key- NLD Value- Dutch
Key- ENG Value- English
Key- ZUL Value- Zulu

If you want to sort in reversed order then you can use reversed() method of the Comparator class to reverse the sorting order.

Map newMap= langMap.entrySet().stream().sorted(Map.Entry.comparingByValue().reversed())
                            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (k,v)->k,LinkedHashMap::new));

If you want to sort on keys then you can use the following code-

Map newMap = langMap.entrySet().stream().sorted(Map.Entry.comparingByKey())
                     .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (k,v)->k,LinkedHashMap::new));

That's all for this topic How to Sort a HashMap in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How to Sort HashSet in Java
  2. How LinkedList Class Works Internally in Java
  3. Difference Between HashMap And ConcurrentHashMap in Java
  4. How to Sort Elements in Different Order in TreeSet
  5. Fail-Fast Vs Fail-Safe Iterator in Java

You may also like-

  1. Java Multithreading Interview Questions And Answers
  2. Difference Between Encapsulation And Abstraction in Java
  3. strictfp in Java
  4. Try-With-Resources in Java With Examples
  5. String in Java Tutorial
  6. How to Display Time in AM-PM Format in Java
  7. Lazy Initializing Spring Beans
  8. Tips for improving MapReduce performance

1 comment:

  1. Sorting HashMap using values in Java 1.8

    Map langMap = new HashMap();
    langMap.put("ENG", "English");
    langMap.put("NLD", "Dutch");
    langMap.put("ZHO", "Chinese");
    langMap.put("BEN", "Bengali");
    langMap.put("ZUL", "Zulu");
    langMap.entrySet().stream().sorted(Map.Entry.comparingByValue()).forEach(System.out::println);

    ReplyDelete