How to Sort HashMap in Java based on Keys and Values (original) (raw)
HashMap is not meant to keep entries in sorted order, but if you have to sort HashMap based upon keys or values, you can do that in Java. Sorting HashMap on keys is quite easy, all you need to do is to create a TreeMap by copying entries from HashMap. TreeMap is an implementation of SortedMap and keeps keys in their natural order or a custom order specified by Comparator provided while creating TreeMap. This means you can process entries of HashMap in sorted order but you cannot pass a HashMap containing mappings in a specific order, this is just not possible because HashMap doesn't guarantee any order.
On other hand, sorting HashMap by values is rather complex because there is no direct method to support that operation. You need to write code for that. In order to sort HashMap by values you can first create a Comparator, which can compare two entries based on values.
Then get the Set of entries from Map, convert Set to List, and use Collections.sort(List) method to sort your list of entries by values by passing your customized value comparator. This is similar to how you sort an ArrayList in Java.
Half of the job is done by now. Now create a new LinkedHashMap and add sorted entries into that. Since LinkedHashMap guarantees insertion order of mappings, you will finally have a Map where contents are sorted by values.
5 Steps to sort HashMap by values
One difference between sorting HashMap by keys and values is that it can contain duplicate values by not duplicate keys. You cannot use TreeMap here because it only sorts entries by keys. In this case, you need to :
- Get all entries by calling entrySet() method of Map
- Create a custom Comparator to sort entries based upon values
- Convert entry set to list
- Sort entry list by using Collections.sort() method by passing your value comparator
- Create a LinkedHashMap by adding entries in sorted order.
Steps to sort HashMap by keys
There are two ways to sort HashMap by keys, first by using TreeMap and second by using LinkedHashMap. If you want to sort using TreeMap then it's simple, just create a TreeMap by copying the content of HashMap.
On the other hand, if you want to create a LinkedHashMap then you first need to get a key set, convert that Set to a List, sort that List, and then add them into LHM in the same order. Remember HashMap can contain one null key but duplicate keys are not allowed.
HashMap Sorting by Keys and Values in Java Example
Here is our sample Java program to sort a HashMap first by keys and then by values. This program is divided into two part, the first part sorts HashMap by keys, and the second part sorts it by values. The second part is more tricky the first part as there is no native Map implementation that supports any order for values.
In order to sort a HashMap by values, we had to create our own Comparator implementation which compares each entry by values to arrange them in a particular order. You can see that our valueComparator overrides compare() method and accepts two entries. Later it retrieves values from those entries and compare them and return result.
Since there is no method in Java Collection API to sort Map, we need to use Collections.sort() method which accepts a List. This involves creating a temporary ArrayList with entries for sorting purpose and then again copying entries from sorted ArrayList to a new LinkedHashMap to keep them in sorted order.
Finally, we create a HashMap from that LinkedHashMap, which is what we needed.
import java.text.ParseException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap;
/**
- How to sort HashMap in Java by keys and values.
- HashMap doesn't guarantee any order, so you cannot rely on it, even if
- it appear that it storing entries in a particular order, because
- it may not be available in future version e.g. earlier HashMap stores
- integer keys on the order they are inserted but from Java 8 it has changed.
- @author WINDOWS 8 */
public class HashMapSorting{
public static void main(String args[]) throws ParseException {
// let's create a map with Java releases and their code names
HashMap<String, String> codenames = new HashMap<String, String>();
codenames.put("JDK 1.1.4", "Sparkler");
codenames.put("J2SE 1.2", "Playground");
codenames.put("J2SE 1.3", "Kestrel");
codenames.put("J2SE 1.4", "Merlin");
codenames.put("J2SE 5.0", "Tiger");
codenames.put("Java SE 6", "Mustang");
codenames.put("Java SE 7", "Dolphin");
System.out.println("HashMap before sorting, random order ");
Set<Entry<String, String>> entries = codenames.entrySet();
for(Entry<String, String> entry : entries){
System.out.println(entry.getKey() + " ==> " + entry.getValue());
}
// Now let's sort HashMap by keys first
// all you need to do is create a TreeMap with mappings of HashMap
// TreeMap keeps all entries in sorted order
TreeMap<String, String> sorted = new TreeMap<>(codenames);
Set<Entry<String, String>> mappings = sorted.entrySet();
System.out.println("HashMap after sorting by keys in ascending order ");
for(Entry<String, String> mapping : mappings){
System.out.println(mapping.getKey() + " ==> " + mapping.getValue());
}
// Now let's sort the HashMap by values
// there is no direct way to sort HashMap by values but you
// can do this by writing your own comparator, which takes
// Map.Entry object and arrange them in order increasing
// or decreasing by values.
Comparator<Entry<String, String>> valueComparator
= new Comparator<Entry<String,String>>() {
@Override
public int compare(Entry<String, String> e1, Entry<String, String> e2) {
String v1 = e1.getValue();
String v2 = e2.getValue();
return v1.compareTo(v2);
}
};
// Sort method needs a List, so let's first convert Set to List in Java
List<Entry<String, String>> listOfEntries
= new ArrayList<Entry<String, String>>(entries);
// sorting HashMap by values using comparator
Collections.sort(listOfEntries, valueComparator);
LinkedHashMap<String, String> sortedByValue
= new LinkedHashMap<String, String>(listOfEntries.size());
// copying entries from List to Map
for(Entry<String, String> entry : listOfEntries){
sortedByValue.put(entry.getKey(), entry.getValue());
}
System.out.println("HashMap after sorting entries by values ");
Set<Entry<String, String>> entrySetSortedByValue = sortedByValue.entrySet();
for(Entry<String, String> mapping : entrySetSortedByValue){
System.out.println(mapping.getKey() + " ==> " + mapping.getValue());
}
}
}
Output: HashMap before sorting, random order Java SE 7 ==> Dolphin J2SE 1.2 ==> Playground Java SE 6 ==> Mustang J2SE 5.0 ==> Tiger J2SE 1.3 ==> Kestrel J2SE 1.4 ==> Merlin JDK 1.1.4 ==> Sparkler HashMap after sorting by keys in ascending order J2SE 1.2 ==> Playground J2SE 1.3 ==> Kestrel J2SE 1.4 ==> Merlin J2SE 5.0 ==> Tiger JDK 1.1.4 ==> Sparkler Java SE 6 ==> Mustang Java SE 7 ==> Dolphin HashMap after sorting entries by values Java SE 7 ==> Dolphin J2SE 1.3 ==> Kestrel J2SE 1.4 ==> Merlin Java SE 6 ==> Mustang J2SE 1.2 ==> Playground JDK 1.1.4 ==> Sparkler J2SE 5.0 ==> Tiger
That's all about how to sort HashMap by keys and values in Java. Remember, HashMap is not intended to keep entries in sorted order, so if you have a requirement to always keep entries in a particular order, don't use HashMap instead use TreeMap or LinkedHashMap.
This method should only be used to cater to Adhoc needs where you receive a HashMap from some part of legacy code and you have to sort it first to process entries. If you have control of creating the Map initially prefer the right implementation of Map than just HashMap.
> And, now is the quiz time? Does sorting a HashMap really make sense? Shouldn't you be using TreeMap or LinkedHashMap if you need to keep your data in sorted order of keys?