Map is the efficient data structure that stores user-provided data according to the natural order in key-value pairs. It assigns a unique key to each map element. This key is utilized to retrieve the corresponding values from the map. Due to this “key-value” pair format, the selection, retrieval, and sorting of elements becomes a lot easier. 

This guide illustrates the approaches to sorting a map by value in Java by covering the following sections:

  • How to Sort a Map by Value in Java?
  • Sort a Map by Value Using Java 8 Stream API Methods
  • Use of Java “sort()” Method to Sort a Map by Value
  • Use of Java “sort()” Method to Sort a Map by Value Without Lambda Expression
  • Sort a Map by Value Using TreeMap
  • Bonus Tip: Use of TreeMap to Sort a Map by Key

How to Sort a Map by Value in Java?

As already discussed, each key in the map must be unique which helps a lot to access the affiliated value. However, this uniqueness does not apply to values, as more than one key can contain the same values. This makes the sorting a little tricky when the sorting procedure is performed according to allotted values.

Luckily! There are several methods provided by Java to perform the sorting of Maps by value. These methods are explained below.

Sort a Map by Value Using Java 8 Stream API Methods

The Stream API that works on Java 8 or above versions provides a method named “sorted()” to perform sorting over the map. This method accepts a “comparingByValue()” method to perform the sorting according to “values”. This “comparingByValue()” method by default performs sorting in ascending order. However, for sorting in descending order, pass the “Comparator.reverseOrder()” method as a parameter in the “comparingByValue()” method.

Let’s look at the examples mentioned to perform sorting according to different scenarios.

Example 1: Sort a Map in Ascending Order by Integer Value

In this case, the “sorted()” method sorts the map elements according to values assigned to each key:

import java.util.*;
import java.util.stream.Collectors;
//Importing the required Packages
public class SortMap {//define the main method
public static void main(String[] args)
{
  Map<String, Integer> unsortedOriginalMap = Map.of("adam", 1, "zack", 3, "billy", 5, "elon", 2, "david", 4);
  System.out.println("The unsorted original Map: " + unsortedOriginalMap);
  LinkedHashMap<String, Integer> sortedModifiedMap = unsortedOriginalMap.entrySet()
  .stream()
  .sorted(Map.Entry.comparingByValue())
  .collect(Collectors.toMap(
    Map.Entry::getKey,
    Map.Entry::getValue,
    (oldValue, newValue) -> oldValue, LinkedHashMap::new));
  System.out.println("\nThe sorted Modified Map: " + sortedModifiedMap);
}
}

In the above code snippet:

  • First, declare and initialize a map named “unsortedOriginalMap” using the “Map.of()” method.
  • Then, apply the “entrySet()” and “stream()” methods on the created map to convert it into a Stream.
  • Also, apply a “sorted()” method with the “comparingByValue()” method to sort the map according to the “values”.
  • Now, apply the “collect()” method to select each sorted key-value pair and store them in the “sortedModifiedMap” map.

The generated output confirms the sorting of a map by values:

Example 2: Sort a Map in Descending Order by Integer Value

The “Comparator.reverseOrder()” method allows the user to sort a map in reverse order. This method is passed into the “comparingByValue()” method to reverse the indexes of sorted elements:

import java.util.*;
import java.util.stream.Collectors;
//Importing the required Packages
public class SortMap {
//define the main method
public static void main(String[] args)
{
  Map<String, Integer> unsortedOriginalMap = Map.of("adam", 1, "zack", 3, "billy", 5, "elon", 2, "david", 4);
  System.out.println("The unsorted original Map: " + unsortedOriginalMap);
  LinkedHashMap<String, Integer> sortedModifiedMap = unsortedOriginalMap.entrySet()
  .stream()
  .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
  .collect(Collectors.toMap(
    Map.Entry::getKey,
    Map.Entry::getValue,
    (oldValue, newValue) -> oldValue, LinkedHashMap::new));
  System.out.println("\nThe sorted Modified Map: " + sortedModifiedMap);
}
}

The above code is the same as the one we discussed in the previous section. Only the “Comparator.reverseOrder()” method is passed into the “comparingByValue()” method to sort the map elements in reverse/descending order. 

The output for the above code shows the sorting of a List in descending or reverse order:

Example 3: Sort a Map in Ascending and Descending Order by String Type Values

In this example, a Map is sorted according to the allotted String type values for each Map Key. This is done using the “sorted()”, “comparingByValue()” and “Comparator.reverseOrder()” methods:

import java.util.*;
import java.util.stream.Collectors;

public class SortMap {
public static void main(String[] args)
{
//targeted Map
  Map<Double, String> unsorted = Map.of(0.5, "adam", 3.3, "zack", 5.1, "billy", 2.8, "elon", 4.4, "david");
  System.out.println("The unsorted original Map: \n" + unsorted);

//Ascending Sorting by String type Map Values
  LinkedHashMap<Double, String> sortedStringValue = unsorted.entrySet()
  .stream()
  .sorted(Map.Entry.comparingByValue())
  .collect(Collectors.toMap(
    Map.Entry::getKey,
    Map.Entry::getValue,
    (oldValue, newValue) -> oldValue, LinkedHashMap::new));
  System.out.println("\nThe sorted Map in Ascending order: \n" + sortedStringValue);
  //Sorting by String type Map Values in Descending order
  LinkedHashMap<Double, String> sortedReverseValue = unsorted.entrySet()
  .stream()
  .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
  .collect(Collectors.toMap(
    Map.Entry::getKey,
    Map.Entry::getValue,
    (oldValue, newValue) -> oldValue, LinkedHashMap::new));
  System.out.println("\nThe sorted Map in Descending/Reverse order: \n" + sortedReverseValue);
}
}

In the above code snippet:

  • First, Pass the map with a “String” type value to both “sorted()” methods. Also, pass the “comparingByValue()” and “comparingByValue(Comparator.reverseOrder())” methods as their arguments.
  • These argument methods sort the Map according to value in both ascending and descending order.

The output the sorting a Map according to its String type value is shown below:

Example 4: Sort a Map Value Using Custom Comparator

The custom comparator allows users to perform the sorting of Map values according to the requirements. 

This approach helps a lot when the Map value is a custom object, as shown below:

import java.util.*;
//Class for Assigning and retrieving Map Elements
class Candidate {
private String name;
private double exp;
public Candidate(String name, double experience) {
  this.name = name;
  this.exp = experience;
}
public String getName() {
  return name;
}

public double getExp() {
  return exp;
}
@Override
public String toString() {
return ">  {" +
  "Candidate Name= '" + name + '\'' +
  " , Experience= " + exp +
  '}';
}
}
public class SortMap {
public static void main(String[] args)
{
//Inserting Elements into Map Via Class Constructor
  Map<Integer,Candidate> sortedMap = new HashMap<>();
  sortedMap.put(1, new Candidate("Jinnah", 3));
  sortedMap.put(2, new Candidate("David", 1));
  sortedMap.put(3, new Candidate("Angelo", 1.5));
  sortedMap.put(4, new Candidate("Nelson", 2.8));
  sortedMap.put(5, new Candidate("Andrew", 0.7));
  System.out.print("Sorted Map\n");
  sortedMap.entrySet().stream()
  .sorted(Map.Entry.comparingByValue(Comparator.comparing(Candidate::getExp)))
  .forEach(System.out::println);
}
}

The working of the above code is written below:

  • First, create a class “Candidate” and declare two variables namely “name” and “exp”. Assign values to these variables using the class constructor.
  • Next, use a couple of getter methods to retrieve the values for the defined “name” and “exp” variables. Also, override the “toString()” method to return the “name” and “exp” variables in a custom-created String.
  • Define a “main()” method and inside it insert the values in a Map using the “put()” method.
  • This “put()” method accepts the first parameter of a map index number and the second as a value that needs to be inserted. Here, provide the Map values by creating a new object for the “Candidate” class.
  • After that, convert the created Map into a Stream and apply the “Sorted()” method to perform the sorting. 
  • Inside its parenthesis, utilize the “comparingByValue()” and “comparing()” methods. These methods perform the sorting according to the value. This value in our case is “experience” that is retrieved using the “getExp()” method.

The output confirms the sorting of a Map by value using a custom comparator in Java:

Pro Tip:

To perform the reverse sorting using a custom comparator modify the code inside the “sorted()” method with this:

sorted(Map.Entry.comparingByValue(
Comparator.comparing(Candidate::getAge, Comparator.reverseOrder())
))

Use of Java “sort()” Method to Sort a Map by Value

The “sort()” method works with or without the Lambda function to perform the sorting of a Map in a specific order. Moreover, the “Map.Entry” interface converts the List into a Map to make its element accessible:

import java.util.*;
import java.util.Map.Entry;
public class SortMap {//Performing sorting Via sort()
public static LinkedHashMap<String, String> sorter (LinkedHashMap<String, String> map) {
  List <Entry<String, String>> clubOwners = new LinkedList<>(map.entrySet());

  Collections.sort(clubOwners, (val1, val2) -> val1.getValue().compareTo(val2.getValue()));
 
  LinkedHashMap<String, String> output = new LinkedHashMap<String, String>();

  for (Map.Entry<String, String> item : clubOwners) {
  output.put(item.getKey(), item.getValue());
  }
  return output;
}
//Driver Method public static void main(String[] args)
{//Defining the LinkedHashMap
  LinkedHashMap<String, String> Owners = new LinkedHashMap<String, String>();
  Owners.put("Arsenal", "Stan Kroenke");
  Owners.put("Aston Villa", "Nassef Sawiris");
  Owners.put("Liverpool", "John W. Henry");
  Owners.put("Chelsea", "Todd Boehly");
  Owners.put("Fulham", "Shahid Khan");
   Map<String, String> result = sorter(Owners);
  for (Map.Entry mapItem : result.entrySet()) {
  System.out.print("\nKey: " + mapItem.getKey());
  System.out.println("\n Value: " + mapItem.getValue());
  }
}
}

The working of the mentioned code is as follows:

  • First, create a method named “sorter()” with the return type LinkedHashMap. It accepts a single LinkedHashMap named “map”.
  • Inside the “sorter()” method, create a List named “clubOwners” and pass the “entrySet” in the List constructor.
  • Next, invoke the “Collections.sort()” method that accepts “to be sort List” and “Lambda Function” as arguments. 
  • The lambda function compares the List values with each other and places the lowest value at the top of the List. 
  • Then, use the “Map.Entry” interface and the “put()” method to convert the created List into a new map “output”.
  • In the “main()” method, define a targeted hashmap named “Owners”. Pass this “Owners” map to the “sorter()” method for sorting Maps underlying elements.
  • Finally, print the keys and values for each Map element on the console.

The output confirms the sorting of a Map by value in Java:

Use of Java “sort()” Method to Sort a Map by Value Without Lambda Expression

The “sort()” method is used with “Comparator” directly to perform sorting in the desired order over a map. This prevents developers from using lambda expressions which can be more complex with the enhancement of requirements. 

For instance, the “sort()” method sorts the map in reverse order without the Lambda expression in the below code block:

import java.util.*;
import java.util.Map.Entry;

public class SortMap {//Performing sorting Via Sort() Method
public static LinkedHashMap<String, String> sorter(LinkedHashMap<String, String> map) {
  List<Map.Entry<String, String> > sortedList =
  new LinkedList<Map.Entry<String, String> >(map.entrySet());

  Collections.sort(sortedList, new Comparator<Map.Entry<String, String> >() {
  public int compare(Map.Entry<String, String> mapIndex1, Map.Entry<String, String> mapIndex2)
    {
    return (mapIndex2.getValue()).compareTo(mapIndex1.getValue());
    }
  });
  LinkedHashMap<String, String> displayMap = new LinkedHashMap<String, String>();
  for (Map.Entry<String, String> mapItem : sortedList) {
      displayMap.put(mapItem.getKey(), mapItem.getValue());
  }
  return displayMap;
}
//Defining the Main Method
public static void main(String[] args)
{//Declaring and Initializing the LinkedHashMap
  LinkedHashMap<String, String> Owners = new LinkedHashMap<String, String>();
  Owners.put("Arsenal", "Stan Kroenke");
  Owners.put("Aston Villa", "Nassef Sawiris");
  Owners.put("Liverpool", "John W. Henry");
  Owners.put("Chelsea", "Todd Boehly");
  Owners.put("Fulham", "Shahid Khan");
 
  Map<String, String> result = sorter(Owners);
  //Displaying Sorted Map
  for (Map.Entry<String, String> mapItem : result.entrySet()) {
  System.out.print("\nKey: " + mapItem.getKey());
  System.out.println("\n Value: " + mapItem.getValue());
  }
}
}

The working of the above code is listed below:

  • First, create a method “sorter()” that accepts a single LinkedHashMap named “map”. Also, Create a new List “sortedList” having the type of “Entry” interface. 
  • Then, invoke the “Collections.sort()” method with the List and “Comparator” instance as an argument.
  • Use the Map.Entry interface and pass the top two indexes of Map as an argument for the “compare()” method. This method compares both index values and returns them in reverse/descending order.
  • Now, declare a new LinkedHashMap named “displayMap” and use the enhanced “for” loop to insert the values of a “sortedList” List in it.
  • This “sortedList” is then returned by the “compare()” method as the final result.
  • In the “main()” method, initialize the targeted map, and pass it to the “sorter()” method. 
  • Finally, print the returned result on the console window with the help of an enhanced for loop.

The output confirms that the provided Map is now sorted by values:

Sort a Map by Value Using TreeMap

The “TreeMap” is a versatile data structure that stores data collection in a sorted or ordered manner. It is suitable for scenarios like efficient retrieval of subsets or range-based queries. It stores data in natural ordering or according to a specified comparator by itself. The “TreeMap” offers methods like “ceilingKey”, “floorKey”, and “higherKey” to handle range-based queries.

Take a look at the below code block to sort a Map according to Map values using the TreeMap custom Comparator:

import java.util.*;
import java.util.Map.Entry;
//Importing Required Packages

public class SortMap{//Performing sorting Via TreeMap in Ascending
public static void sorter(TreeMap<String, Double> ownersMap) {
  SortedSet<Map.Entry<String, Double>> sortedSet = new TreeSet<>(new Comparator<Map.Entry<String, Double>>() {
  public int compare(Map.Entry<String, Double> firstIndex, Map.Entry<String, Double> secondIndex) {
  return firstIndex.getValue().compareTo(secondIndex.getValue());
  }
});

sortedSet.addAll(ownersMap.entrySet());

for (Entry<String, Double> item : sortedSet) {
  System.out.println("Key = " + item.getKey() +
  ", Value = " + item.getValue());
  }
}
//Main Method
public static void main(String args[]) {
  TreeMap<String, Double> Owners = new TreeMap<>();
  Owners.put("Arsenal", 81.2);
  Owners.put("Aston Villa", 60.7);
  Owners.put("Liverpool", 89.8);
  Owners.put("Chelsea", 75.9);
  Owners.put("Fulham", 67.4);

  sorter(Owners);
}
}

 The working of the above code is written below:

  • First, define a custom method “sorter()” which accepts a single “TreeMap” named “ownersMap”. Inside it, create a new TreeSet named “sortedSet” and pass the custom comparator as the TreeSet constructor to store the values of HashMap.
  • In the Comparator block, define another method “compare()” which accepts the two indexes of the created “sortedSet”. The values of both indexes are then checked and returned in sorted order by this method.
  • Next, select and insert all elements of the “ownersMap” TreeMap into the “sortedSet” TreeSet using the “addAll()” method. 
  • After that, display the elements of Sorted TreeSet over the console via an enhanced “for” loop.
  • Finally, initialize the “main()” method. Inside it, declare and initialize the TreeMap named “Owners”. Also, pass this “Owners” TreeMap as an argument in the “sorter()” method.

The below output confirms the generation of a sorted Map by value in Java:

Bonus Tip: Use of TreeMap to Sort a Map by Key

The “TreeMap” allows users to sort a Map according to each key residing in the TreeMap. It is a default nature of TreeMap(Sorting according to Keys) so there is no need to use Comparator. If the user passes an unsorted map into TreeMap, then the map will by default get sorted according to their Key:

import java.util.*;
public class SortMap {
//Performing sorting Via TreeMap
  public static TreeMap<String, Double> sorter(Map<String, Double> targetMap) {
  TreeMap<String, Double> sorted = new TreeMap<>((targetMap));
  return sorted;
  }
//Display Method
  public static void DisplayTreeMap(TreeMap<String, Double> sortedMap) {
  for (Map.Entry<String, Double> item : sortedMap.entrySet()) {
    System.out.println("Key = " + item.getKey() + ", Value = " + item.getValue());
  }
  }//main Method
public static void main(String args[]) {//Declaring and Initializing the Targeted Map
  Map<String, Double> Owners = new HashMap<>();
  Owners.put("Arsenal", 81.2);
  Owners.put("Aston Villa", 60.7);
  Owners.put("Liverpool", 89.8);
  Owners.put("Chelsea", 75.9);
  Owners.put("Fulham", 67.4);

  TreeMap<String, Double> sortedMap = sorter(Owners);
  DisplayTreeMap(sortedMap);
}
}

The above-mentioned code works like this:

  • First, define a method “Owners” having the return type of “TreeMap” and it accepts the “targetMap” which needs to be sorted.
  • Next, declare a new TreeMap named “sorted” and store the received “targetMap” in it. To sort the “targetMap” according to Key and return the “sorted” TreeMap.
  • Then, define another method “DisplayTreeMap()” accepting a single TreeMap named “sortedMap”. It contains an enhanced “for” loop that traverses and displays the Keys and corresponding values on the console. 
  • Finally, define a Map inside the “main()” method and pass it to the “sorted()” method. Store the result in “TreeMap” and pass it as an argument in the “DisplayTreeMap()” method. 
  • These methods sort the Map by converting it into “TreeMap” and then display its elements on the console.

The output confirms the sorting of a Map by Key in Java Using TreeMap:

That’s all about sorting a Map by Value in Java.

Conclusion

In Java, to sort a map by value, use the “stream()”, “sorted()”, and “collect()” methods offered by Java 8  Stream API. The Stream API methods perform sorting on collections expressively.  It generates a new sorted stream from the collection as a result. Alternatively, use the “sort()” method to sort the specific collection(Map) or use the “TreeMap” with a custom-defined comparator. The “TreeMap” data structure by default performs sorting over elements and arranges them in natural order. This article has illustrated the concepts of sorting a Map by value in Java.