Sort Map by keys in Java
This post will discuss various methods to sort map in Java according to the natural ordering of its keys.
1. Using TreeMap
TreeMap is a Red-Black tree-based implementation of Map, which is sorted according to its keys’ natural ordering. We can pass an unsorted map to the TreeMap constructor, which will then construct a new tree map containing the same mappings as the given map but ordered according to its keys’ natural ordering.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import java.util.HashMap; import java.util.Map; import java.util.TreeMap; class Main { // Generic method to sort map by keys using `TreeMap` public static <K, V> Map<K, V> sortByKeys(Map<K, V> unsortedMap) { // construct a `TreeMap` from the given map and return it return new TreeMap<>(unsortedMap); } public static void main(String[] args) { Map<String, String> country = new HashMap<>(); country.put("India", "New Delhi"); country.put("USA", "Washington D.C."); country.put("Japan", "Tokyo"); country.put("China", "Beijing"); country = sortByKeys(country); System.out.println("Sorted map by keys :\n" + country); } } |
Output:
Sorted map by keys :
{China=Beijing, India=New Delhi, Japan=Tokyo, USA=Washington D.C.}
Using Guava’s TreeMap:
Google’s Guava library also provides TreeMap implementation, which we can use to create a mutable, empty TreeMap instance, which is sorted according to a Comparator provided at map creation time. We can pass Guava’s Ordering.natural() for the natural ordering of keys.
|
1 2 3 4 5 6 7 |
// Generic method to sort map by keys in Java using Guava public static <K, V> TreeMap<K, V> sortByKeys(Map<K, V> unsortedMap) { TreeMap<K, V> treeMap = Maps.newTreeMap((Comparator<K>) Ordering.natural()); treeMap.putAll(unsortedMap); return treeMap; } |
2. Using LinkedHashMap
LinkedHashMap is a hash table and linked list implementation of the Map interface, with predictable iteration order, which is the order in which keys were inserted into the map. We can use this property to produce a copy of a map that is sorted according to the natural ordering of its keys.
The idea is to create a list of keys present on the map and sort it. Then, we insert a key-value pair in an empty LinkedHashMap for every key in the sorted list. Keys will sort the resultant LinkedHashMap.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
import java.util.*; class Main { // Generic method to sort map by keys using `LinkedHashMap` public static <K extends Comparable, V> Map<K, V> sortByKeys(Map<K, V> map) { // create a list of map keys and sort it List<K> keys = new ArrayList(map.keySet()); Collections.sort(keys); // create an empty insertion-ordered `LinkedHashMap` Map<K, V> linkedHashMap = new LinkedHashMap<>(); // for every key in the sorted list, insert key-value // pair in `LinkedHashMap` for (K key: keys) { linkedHashMap.put(key, map.get(key)); } return linkedHashMap; } public static void main(String[] args) { Map<String, String> country = new HashMap<>(); country.put("India", "New Delhi"); country.put("USA", "Washington D.C."); country.put("Japan", "Tokyo"); country.put("China", "Beijing"); country = sortByKeys(country); System.out.println("Sorted map by keys :\n" + country); } } |
Output:
Sorted map by keys :
{China=Beijing, India=New Delhi, Japan=Tokyo, USA=Washington D.C.}
Here’s an equivalent version using the Stream API.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
import java.util.*; import java.util.stream.Collectors; class Main { // Generic method to sort map by keys using `LinkedHashMap` public static <K extends Comparable, V> Map<K, V> sortByKeys(Map<K, V> map) { // create a list of map keys and sort it List<K> keys = new ArrayList(map.keySet()); Collections.sort(keys); // for every key in the sorted list, insert key-value pair in an // insertion-ordered `LinkedHashMap` return keys.stream().collect(Collectors.toMap(key -> key, map::get, (a, b) -> b, LinkedHashMap::new)); } public static void main(String[] args) { Map<String, String> country = new HashMap<>(); country.put("India", "New Delhi"); country.put("USA", "Washington D.C."); country.put("Japan", "Tokyo"); country.put("China", "Beijing"); country = sortByKeys(country); System.out.println("Sorted map by keys :\n" + country); } } |
Output:
Sorted map by keys :
{China=Beijing, India=New Delhi, Japan=Tokyo, USA=Washington D.C.}
3. Using Java 8
We can also use Java 8 Stream to sort map by keys. Following are the steps:
- Obtain stream from the set view of the mappings contained in the map.
- Sort the stream in natural order of keys using
Stream.sorted()method by passing comparator returned byMap.Entry.comparingByKey(). - Collect all sorted elements in a
LinkedHashMapusingStream.collect()withCollectors.toMap().
Please note that a stream is a sequence of items, not a sequence of key/value pairs. So, we can’t construct a map out of a stream without specifying how to extract keys and values from it. Java 8 provides Collectors.toMap() method for this purpose. We need to use an overloaded version of toMap() that returns LinkedHashMap instead of HashMap to retain the sorted order.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.stream.Collectors; class Main { public static void main(String[] args) { Map<String, String> country = new HashMap<>(); country.put("India", "New Delhi"); country.put("USA", "Washington D.C."); country.put("Japan", "Tokyo"); country.put("China", "Beijing"); // Sort map by keys in Java 8 and above country = country.entrySet() // Set<Entry<String, String>> .stream() // Stream<Entry<String, String>> .sorted(Map.Entry.comparingByKey()) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new)); System.out.println("Sorted map by keys :\n" + country); } } |
Output:
Sorted map by keys :
{China=Beijing, India=New Delhi, Japan=Tokyo, USA=Washington D.C.}
Following is another approach that doesn’t involve using a collector. It uses the Stream.forEachOrdered() method on the sorted stream that inserts each element of the stream into a new LinkedHashMap.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; class Main { public static void main(String[] args) { Map<String, String> country = new HashMap<>(); country.put("India", "New Delhi"); country.put("USA", "Washington D.C."); country.put("Japan", "Tokyo"); country.put("China", "Beijing"); // Sort map by keys in Java 8 and above Map<String, String> sortedMap = new LinkedHashMap<>(); country.entrySet() // Set<Entry<String, String>> .stream() // Stream<Entry<String, String>> .sorted(Map.Entry.comparingByKey()) .forEachOrdered(entry -> sortedMap.put(entry.getKey(), entry.getValue())); System.out.println("Sorted map by keys :\n" + sortedMap); } } |
Output:
Sorted map by keys :
{China=Beijing, India=New Delhi, Japan=Tokyo, USA=Washington D.C.}
That’s all about sorting Map by keys in Java.
Related Post:
References:
1. TreeMap Javadoc – Java SE 8
2. LinkedHashMap Javadoc – Java SE 8 Javadoc
Thanks for reading.
To share your code in the comments, please use our online compiler that supports C, C++, Java, Python, JavaScript, C#, PHP, and many more popular programming languages.
Like us? Refer us to your friends and support our growth. Happy coding :)