Sort a HashMap in Java

1. Introduction

In this quick tutorial, we’ll learn how to sort a HashMap in Java.

More specifically, we’ll look at sorting HashMap entries by their key or value using:

  • TreeMap
  • ArrayList and Collections.sort()
  • TreeSet
  • Using the Stream API, and finally,
  • Using the Guava library

2. Using a TreeMap

As we know, keys in TreeMap are sorted using their natural order. This is a good solution when we want to sort the key-value pairs by their key. So the idea is to push all the data from our HashMap into the TreeMap.

For starters, let’s define a HashMap and initialize it with some data:

Map<String, Employee> map = new HashMap<>();

Employee employee1 = new Employee(1L, "Mher");
map.put(employee1.getName(), employee1);
Employee employee2 = new Employee(22L, "Annie");
map.put(employee2.getName(), employee2);
Employee employee3 = new Employee(8L, "John");
map.put(employee3.getName(), employee3);
Employee employee4 = new Employee(2L, "George");
map.put(employee4.getName(), employee4);

For the Employee class, note that we’ve implemented Comparable:

public class Employee implements Comparable<Employee> {

    private Long id;
    private String name;

    // constructor, getters, setters

    // override equals and hashCode
    @Override
    public int compareTo(Employee employee) {
        return (int)(this.id - employee.getId());
    }
}

Next, we store the entries in the TreeMap by using its constructor:

TreeMap<String, Employee> sorted = new TreeMap<>(map);

Or, the putAll method to copy the data:

TreeMap<String, Employee> sorted = new TreeMap<>();
sorted.putAll(map);

And that’s it! To make sure our map entries are sorted by key, let’s print them out:

Annie=Employee{id=22, name='Annie'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Mher=Employee{id=1, name='Mher'}

As we see, the keys are sorted in natural order.

3. Using ArrayList

Of course, we can sort the entries of the map with the help of ArrayList. The key difference from the previous method is that we don’t maintain the Map interface here.

3.1. Sort by Key

Let’s load the key set into an ArrayList:

List<String> employeeByKey = new ArrayList<>(map.keySet());
Collections.sort(employeeByKey);

And the output is:

[Annie, George, John, Mher]

3.2. Sort by Value

Now, what if we want to sort our map values by the id field of Employee object? We can use an ArrayList for that, too.

First, let’s copy the values into the list:

List<Employee> employeeById = new ArrayList<>(map.values());

And after that, we sort it:

Collections.sort(employeeById);

Remember that this works because Employee implements the Comparable interface. Otherwise, we’d need to define a manual comparator for our call to Collections.sort.

To check the results, we print the employeeById:

[Employee{id=1, name='Mher'}, 
Employee{id=2, name='George'}, 
Employee{id=8, name='John'}, 
Employee{id=22, name='Annie'}]

As we see, the objects are sorted by their id field.

4. Using a TreeSet 

In case we don’t want to accept duplicate values in our sorted collection, there is a nice solution with TreeSet.

First, let’s add some duplicate entries to our initial map:

Employee employee5 = new Employee(1L, "Mher");
map.put(employee5.getName(), employee5);
Employee employee6 = new Employee(22L, "Annie");
map.put(employee6.getName(), employee6);

4.1. Sort by Key

To sort the map by its key entries:

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

Let’s print the keySet and see the output:

[Annie, George, John, Mher]

Now we have the map keys sorted without the duplicates.

4.2. Sort by Value

Likewise, for the map values, the conversion code looks like:

SortedSet<Employee> values = new TreeSet<>(map.values());

And the results are:

[Employee{id=1, name='Mher'}, 
Employee{id=2, name='George'}, 
Employee{id=8, name='John'}, 
Employee{id=22, name='Annie'}]

As we can see, there are no duplicates in the output. This works with custom objects when we override equals and hashCode.

5. Using Lambdas and Streams

Since the Java 8, we can use the Stream API and lambda expressions to sort the map. All we need is to call the sorted method over the map’s stream pipeline.

5.1. Sort by Key

To sort by key, we use the comparingByKey comparator:

map.entrySet()
  .stream()
  .sorted(Map.Entry.<String, Employee>comparingByKey())
  .forEach(System.out::println);

The final forEach stage prints out the results:

Annie=Employee{id=22, name='Annie'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Mher=Employee{id=1, name='Mher'}

By default, the sorting mode is ascending.

5.2. Sort by Value

Of course, we can sort by the Employee objects as well:

map.entrySet()
  .stream()
  .sorted(Map.Entry.comparingByValue())
  .forEach(System.out::println);

As we see, the code above prints out a map sorted by the id fields of Employee objects:

Mher=Employee{id=1, name='Mher'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Annie=Employee{id=22, name='Annie'}

Additionally, we can collect the results into a new map:

Map<String, Employee> result = map.entrySet()
  .stream()
  .sorted(Map.Entry.comparingByValue())
  .collect(Collectors.toMap(
    Map.Entry::getKey, 
    Map.Entry::getValue, 
    (oldValue, newValue) -> oldValue, LinkedHashMap::new));

Note that we collected our results into a LinkedHashMap. By default, Collectors.toMap returns a new HashMap, but as we know, HashMap doesn’t guarantee iteration order, while LinkedHashMap does.

6. Using Guava

Lastly, a library that allows us to sort the HashMap is Guava. Before we start, it’ll be useful to check our write-up about maps in Guava.

First, let’s declare an Ordering as we want to sort our map by Employee’s Id field:

Ordering naturalOrdering = Ordering.natural()
  .onResultOf(Functions.forMap(map, null));

Now, all we need is to use ImmutableSortedMap to illustrate the results:

ImmutableSortedMap.copyOf(map, naturalOrdering);

And once again, the output is a map ordered by the id field:

Mher=Employee{id=1, name='Mher'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Annie=Employee{id=22, name='Annie'}

7. Summary

In this article, we reviewed a number of ways to sort a HashMap by key or by value.

And we took a close look at how we can do this when the attribute is a custom class by implementing Comparable.

Finally, as always, the code used during the discussion can be found over on GitHub.