How to Sort a HashMap by Key in Java
-
Sort the Keyset Using the
TreeMap
Class in Java - Sorting the Keyset Using the Java 8 Functions
- Understand the Map Initialization Stream Function in Java
- Understand the Map Transformation Stream Function in Java
The term HashMap
in Java language is the collection derived from the Map
interface. This collection or class is present in the java.util
package and stores the data in key-value pair. Note that there cannot be two keys on the map. If the duplicate key gets inserted, then the value of the respective key gets replaced by the newer value.
Sort the Keyset Using the TreeMap
Class in Java
Below is the code block to demonstrate the sorting of a HashMap
by its key.
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
public class HashMapSortByKey {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("2", "Value5");
map.put("3", "Value1");
map.put("1", "Value2");
map.put("4", "Value3");
map.put("9", "Value4");
map.put("hi11", "Value6");
map.put("hi0", "Value7");
System.out.print("Unordered List: ");
for (String s : map.keySet()) {
System.out.print(" " + s);
}
System.out.println();
System.out.print("Ordered List: ");
TreeMap<String, String> map1 = new TreeMap<>(map);
for (String s : map1.keySet()) {
System.out.print(" " + s);
}
}
}
In the code block above, the map
object is declared using the default constructor of HashMap
with the new
keyword. The statement creates an instance of the HashSet
class and assigns the value to the Map
interface reference. The types are compatible as the HashMap
class implements the Map
interface internally.
The map gets initialized with some set of key values. The insertion happens using the put
method that binds the key to its specified value. The method returns the previous value
if the key was already present in the map and overrides the previous value with a specified one. The function returns a null
value when the key is not already present in the map. It throws IllegalArgumentException
if the property of the key or value prohibits the value from insertion.
Now for iterating over the map, the for-each
loop gets used. The map.keySet
function returns the Set
format of all the keys in the map. The keyset function gets a collection in the for-each
loop over which the variable can iterate; hence, printing the keys. It will print the values in an unordered format, and there’s no well-defined manner in which the user will get the output.
To sort the map keys, the TreeSet
class gets used. The map
variable is given as a constructor parameter in the TreeSet
constructor at the time of instantiation. The class implements the Comparable
interface to sort the keys. When the resultant map, map1
, gets printed, it prints the sorted keys in the output.
Below is the output of the code block above.
Output:
Unordered List: 1 hi11 2 3 4 9 hi0
Ordered List: 1 2 3 4 9 hi0 hi11
Sorting the Keyset Using the Java 8 Functions
Java 8 provides a privilege of functional programming, which helps in working over the chain functions. In the program below, it is seen that instantiation and initialization happen in a statement. Whereas in the first example code, it is a tedious task to populate the map. Understanding the Streams
and functions to instantiate the map in a single statement is given below.
Streams
is an interface in the java.util
package that provides flexibility to work over the sequence of operations in a single go. The Streams
works in the pipeline where an emitter emits the data; it gets filtered, processed, transformed, and much more as per the users’ need.
import static java.util.AbstractMap.SimpleEntry;
import static java.util.stream.Collectors.toMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Stream;
public class HashMapSortByKey {
public static void main(String[] args) {
Map<String, String> map =
Stream
.of(new SimpleEntry<>("key6", "value1"), new SimpleEntry<>("key12", "value2"),
new SimpleEntry<>("key9", "value3"))
.collect(toMap(SimpleEntry::getKey, SimpleEntry::getValue));
System.out.print("Unordered List: ");
for (String s : map.keySet()) {
System.out.print(" " + s);
}
Map<String, String> mapSortedByKey =
map.entrySet()
.stream()
.sorted(Map.Entry.<String, String>comparingByKey().reversed())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(oldVal, newValue) -> oldValue, LinkedHashMap::new));
System.out.println();
System.out.print("Ordered List: ");
for (String s1 : mapSortedByKey.keySet()) {
System.out.print(" " + s1);
}
}
}
Understand the Map Initialization Stream Function in Java
Firstly, the Stream
calls the of()
function that returns the specified stream in sequential order. The function creates objects of the SimpleEntry
class to create mappings of the key-value form. The class implements the Entry
interface and has the entrySet
method that returns the collection view of the map.
Once the key-value entries get formed, the values are collected to a map using the collect
function. It is a terminal function meaning no more methods can get invoked after the collect function. The function packages or binds the stream values in the desired data structures.
The input given as a parameter is always a Collector
reference. The toMap
is a static function in the Collectors
class that returns a Collector
that binds the stream elements in a Map. The function takes a key Mapper and key Value Function
as its parameter. Now, the method reference ::
operator means calling the functions of the specified class.
In the key Mapper, the getKey
function extracts the key from the populated EntrySet
stream. Similarly, in the key Value function, the getValue
function gets called to get the value from the EntrySet
stream.
The Collector
Function
variables from the code above are the functional interfaces in Java that have a single abstract method for the functionality. The abstract method’s definitions get defined in classes that implement them.
Understand the Map Transformation Stream Function in Java
Over the map
instance that just formed, the entrySet
function gets invoked. The function returns the set view of the map entries and is present in the Map interface. Over these entries, the stream
method is called to convert the entries in the sequential stream. Over the stream of entries, the sorted
function gets invoked.
It takes a Comparator
to compare the Stream
elements. The sorted function finally returns the sorted stream of the given entries. The comparingByKey
function returns the Map.Entry
comparator with the default ordering on the key. The comparator returns a key set; if a key found is null, it throws NullPointerException
from the function.
When the entry set is retrieved, the reversed
function gets called to reverse the elements’ order in the collection. Finally, the collect
function gets invoked over the map stream. The function is a terminal operator, and hence, no operations can get called after the collect
function. Into the function, the toMap
function gets called to transform the stream into the map.
The function takes four parameters: the keyMapper
is a function that produces keys, the valueMapper
is a mapping function that creates its values, the mergeFunction
is a BinaryOperator
that merges a function, and the mapSupplier
is a Supplier
function which returns a new, empty Map where the results get inserted. Finally, the resultant console output gets printed above.
Output:
Unordered List: key12 key6 key9
Ordered List: key9 key6 key12
Rashmi is a professional Software Developer with hands on over varied tech stack. She has been working on Java, Springboot, Microservices, Typescript, MySQL, Graphql and more. She loves to spread knowledge via her writings. She is keen taking up new things and adopt in her career.
LinkedIn