How to sort a map by value
Short answer
Sort the entrySet() pairs with Map.Entry.comparingByValue() and collect them into a LinkedHashMap, which keeps the order:
void main() {
Map<String, Integer> scores = Map.of("Anna", 82, "Oleg", 95, "Boris", 67);
Map<String, Integer> sorted = scores.entrySet().stream()
.sorted(Map.Entry.comparingByValue())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a, LinkedHashMap::new));
IO.println(sorted);
}Output:
{Boris=67, Anna=82, Oleg=95}Descending order
Pass a reverse comparator to comparingByValue():
void main() {
Map<String, Integer> scores = Map.of("Anna", 82, "Oleg", 95, "Boris", 67);
scores.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.forEach(e -> IO.println(e.getKey() + " " + e.getValue()));
}Output:
Oleg 95
Anna 82
Boris 67Top N
Add limit() to get the top few:
void main() {
Map<String, Integer> views = Map.of("home", 500, "blog", 320, "about", 40, "shop", 410);
var top = views.entrySet().stream()
.sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
.limit(2)
.map(Map.Entry::getKey)
.toList();
IO.println(top);
}Output:
[home, shop]Common mistake
Collecting the sorted stream with a plain Collectors.toMap(). It creates a HashMap, and the order is lost again:
void main() {
Map<String, Integer> scores = Map.of("Anna", 82, "Oleg", 95, "Boris", 67);
var result = scores.entrySet().stream()
.sorted(Map.Entry.comparingByValue())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
IO.println(result);
}Output:
{Boris=67, Oleg=95, Anna=82}Always pass LinkedHashMap::new as the fourth argument.
Functions used in this recipe
- Map.Entry — A single key and value pair of a map.
- Collectors.toMap() — A collector that builds a map from stream elements.
- LinkedHashMap — A map that remembers the insertion order of keys.
- Map.entrySet() — Returns all key and value pairs for iteration.