A standard Java Map (like a HashMap) is designed for fast lookups, but it does not guarantee any order of its elements. Sorting Map entries by their keys is easy, but sorting Map entries by their values requires converting the map entries into a stream, applying a comparator, and collecting the ordered elements back into a Map structure that remembers insertion order.
Let's look at how we sort Map values using a simple leaderboard wall analogy.
Imagine you run a company. You have a folder (the unsorted HashMap) containing records matching salary numbers to Employee cards (e.g. key `500` pointing to Employee `S1`). Because they are inside a folder, they are shuffled in no particular order.
You want to display a sorted ranking wall (the leaderboard) from highest salary to lowest:
- You pull the cards out of the folder and slide them onto a conveyor belt one-by-one (converting map entries to a Stream).
- As the cards move, a sorting manager compares their salaries (the values) and arranges them in
descending order (using
Map.Entry.comparingByValue(...)). - Finally, you pin the sorted cards onto a display board that holds them in the exact order they arrive
(collecting them into a
LinkedHashMap). Now, anyone looking at the wall sees the employees ordered perfectly by their salaries!
Walkthrough of the Main Method Scenario
Let's trace how the program executes step-by-step from the entry point of the main method:
The program sets up a HashMap and registers four employee cards with their salaries as the key:
Map<Integer, TestEmployee> salaryEmployeeMap = new HashMap<>();
salaryEmployeeMap.put(500, new TestEmployee(500, "S1", 1));
salaryEmployeeMap.put(800, new TestEmployee(800, "S2", 2));
...
The program enters the sorting function and starts a Java Stream pipeline:
salaryEmployeeMap.entrySet().stream()
This retrieves the key-value entries of the Map and places them into the stream conveyor belt.
The stream sorts the entries based on their employee values:
.sorted(Map.Entry.comparingByValue((o1, o2) -> Integer.compare(o2.getSalary(), o1.getSalary())))
The comparator compares the salary of the second object o2 against the first o1.
Since o2 is placed first in the comparison, it forces a descending sort order
(highest salary first):
- S4 (900) vs. S2 (800) -> S4 is larger, moves to the front.
- The resulting sorted order of employee names becomes: S4, S2, S1, S3.
Finally, the sorted elements are iterated over and added to the output container:
.forEach(eachEntry -> output.put(eachEntry.getValue().getName(), eachEntry.getValue().getSalary()));
Because `output` is a LinkedHashMap, it remembers the order in which entries were inserted, successfully preserving the sorted leaderboard ranking!
Java Implementation
Below is the complete Java code demonstrating Map value sorting using Java Streams:
package io.practise.accolite;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class Example {
public static void main(String[] args) {
Map<Integer, TestEmployee> salaryEmployeeMap = new HashMap<>();
TestEmployee te1 = new TestEmployee(500, "S1", 1);
TestEmployee te2 = new TestEmployee(800, "S2", 2);
TestEmployee te3 = new TestEmployee(200, "S3", 3);
TestEmployee te4 = new TestEmployee(900, "S4", 4);
salaryEmployeeMap.put(te1.getSalary(), te1);
salaryEmployeeMap.put(te2.getSalary(), te2);
salaryEmployeeMap.put(te3.getSalary(), te3);
salaryEmployeeMap.put(te4.getSalary(), te4);
Map<String, Integer> output = sortBasedOnValues(salaryEmployeeMap);
System.out.println(output);
// Outputs: {S4=900, S2=800, S1=500, S3=200}
}
private static Map<String, Integer> sortBasedOnValues(Map<Integer, TestEmployee> salaryEmployeeMap) {
LinkedHashMap<String, Integer> output = new LinkedHashMap<>();
salaryEmployeeMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue((o1, o2) -> Integer.compare(o2.getSalary(), o1.getSalary())))
.forEach(eachEntry -> output.put(eachEntry.getValue().getName(), eachEntry.getValue().getSalary()));
return output;
}
}
class TestEmployee {
private int salary;
private String name;
private int id;
public TestEmployee(int salary, String name, int id) {
this.salary = salary;
this.name = name;
this.id = id;
}
public int getSalary() {
return salary;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
@Override
public String toString() {
return "TestEmployee{" +
"salary=" + salary +
", name='" + name + '\'' +
", id=" + id +
'}';
}
}
Conclusion
Standard HashMaps cannot maintain ordering. Converting Map entries into a stream and sorting them using
Map.Entry.comparingByValue(), then collecting them into a LinkedHashMap is the most clean and
readable way to sort Map entries by their values in Java!