Core Java

Sorting a HashMap In Java

Introduction:

In this tutorial, we’ll learn how to sort a Java HashMap. We can sort a HashMap either by keys or by values. We’ll discuss both of these strategies.

Sorting a Java HashMap:

To follow along with the rest of the article, let’s first construct a HashMap:

HashMap<Integer, Student> map = new HashMap<>();

map.put(1003, new Student(1003, "Sam"));
map.put(1005, new Student(1005, "Joseph"));
map.put(1001, new Student(1001, "Kate"));
map.put(1002, new Student(1002, "Miranda"));
map.put(1004, new Student(1004, "Peter"));

where Student is a POJO with id and name as its fields:

class Student {
    
    private Integer id;
    private String name;
    
    Student(Integer id, String name) {
        this.id = id;
        this.name = name;
    }
    
    public String toString() {
        return "[id="+id + ", name=" + name + "]";
    }
    
}

Now, let’s look at the different approaches we can take to sort a HashMap:

1. Using TreeMap:

As we know, TreeMap is a sorted Map where, by default, the elements are sorted by the natural ordering of their keys. So, a basic approach would be to push all the elements from a HashMap to a TreeMap:

TreeMap<Integer, Student> sortedMap = new TreeMap<>(map);

//Or else

TreeMap<Integer, Student> sortedMap = new TreeMap<>();
sortedMap.putAll(map);

Note that we can either pass the original HashMap itself into the constructor or else we can use a putAll() method. With this, our sortedMap will hold the elements in sorted order of key values:

{1001=[id=1001, name=Kate], 1002=[id=1002, name=Miranda]
, 1003=[id=1003, name=Sam], 1004=[id=1004, name=Peter]
, 1005=[id=1005, name=Joseph]}

2. With ArrayList:

If we just need the sorted keys or values and don’t really care about the Map,  we can rather use an ArrayList. 

Here, we’ll first extract either the keys or the values into an ArrayList and then sort that List using Collections.sort():

List<Integer> mapKeys = new ArrayList<>(map.keySet());
Collections.sort(mapKeys);

//Or
List<Student> mapValues = new ArrayList<>(map.values()); 
Collections.sort(mapValues);

Here, sorting a Map by values will only work when our Student implements Comparable:

public class Student implements Comparable<Student> {

    ...

    public int compareTo(Student other) {
        return this.id.compareTo(other.id);
    }
}

This is so as the values in our map is a custom type object – Student.

3. With TreeSet:

If we also intend to avoid any duplicates in the resulting list of keys or values, we can opt for a TreeSet:

SortedSet<String> mapKeys = new TreeSet<>(map.keySet());

Similarly, we can create a sorted set of map values. However, we’ll have to override the equals() and hashCode() method for this to work for custom objects.

4. Java 8 Streams:

Java 8 onwards, we can use the Stream API to sort our map. To sort a Java Map using keys, we’ll have:

Map<Integer, Student> sortedMap = map.entrySet()
                                  .stream()
                                  .sorted(Map.Entry.comparingByKey())
                                  .collect(Collectors
                                    .toMap(Map.Entry::getKey,
                                           Map.Entry::getValue,
                                           (e1, e2) -> e1,
                                           LinkedHashMap::new));

Here, we have collected the sorted map into a LinkedHashMap to preserve the sorted ordering

Similarly, to sort by the map by values, we’ll use comparingByValue():

sortedMap = map.entrySet()
              .stream()
              .sorted(Map.Entry.comparingByValue())
               .collect(Collectors
                          .toMap(Map.Entry::getKey,
                                 Map.Entry::getValue,
                                 (e1, e2) -> e1,
                                 LinkedHashMap::new));

As usual, when dealing with custom objects, that object must implement the Comparable interface.

We have a detailed article on Java 8 Collectors, which will help you understand Collectors.toMap() method usage.

In order to sort the map in descending order, we can simply use Collections.reverseOrder():

sortedMapDesc = map.entrySet()
                  .stream()
                  .sorted(Collections.reverseOrder(Map.Entry.comparingByKey()))
                  .collect(Collectors
                   .toMap(Map.Entry::getKey,
                          Map.Entry::getValue,
                          (e1, e2) -> e1,
                           LinkedHashMap::new));

Let’s print out sortedMapDesc on the console:

{1005=[id=1005, name=Joseph], 1004=[id=1004, name=Peter],
1003=[id=1003, name=Sam], 1002=[id=1002, name=Miranda],
 1001=[id=1001, name=Kate]}

As we can see, the map is now sorted in the descending order by keys.

Conclusion:

In this article, we covered various approaches for sorting a Java HashMap – using TreeMap, ArrayList or TreeSet. We also covered the Java 8 Stream API sorted() method which can help us sort our map either by keys or values.

 

Be the First to comment.

Leave a Comment

Your email address will not be published. Required fields are marked *