Want to turn the tables and sort in descending order? Bring in Collections.reverseOrder():
map.entrySet()
.stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) // Sort Descending, like an upside-down world! .forEachOrdered(e -> resultMap.put(e.getKey(), e.getValue()));
For a list of top 'n' entries, use the limit(n) method with your stream:
map.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue())
.limit(n) // The "cream of the crop", so to speak. .forEachOrdered(e -> topNMap.put(e.getKey(), e.getValue()));
Dynamic map sorting
When the map changes and you need consistent sorting, use a ValueComparableMap or populate a TreeMap with a predefined comparator:
Create a ValueComparator that can handle equal values and avoid losing keys:
classValueComparatorimplementsComparator<Key> {
Map<Key, Value> base;
publicValueComparator(Map<Key, Value> base){
this.base = base;
}
// We compare by value, but if they tie, we compare by key, like a tiebreaker round!publicintcompare(Key a, Key b){
int valueComparison = base.get(a).compareTo(base.get(b));
return valueComparison != 0 ? valueComparison : a.compareTo(b); // Assuming Key is Comparable }
}
Use the @SuppressWarnings("unchecked") annotation to suppress unchecked cast warnings with a smirk:
After sorting the entrySet, produce an ordered LinkedHashMap:
LinkedHashMap<Key, Value> sortedMap = new LinkedHashMap<>();
for (Entry<Key, Value> entry : entriesSortedByValues) {
sortedMap.put(entry.getKey(), entry.getValue()); // One by one, like a disciplined line at a school cafetaria}
Additional use-cases and pitfalls
Streams with custom Comparators
Comparator<Entry<Key, Value>> customComparator = // Define what's best for your requirementsmap.entrySet().stream().sorted(customComparator) // Apply the "special sauce" .collect(Collectors.toMap(
Entry::getKey,
Entry::getValue,
(e1, e2) -> e1,
LinkedHashMap::new ));
Managing duplicate values
While collecting, provide a merge function to handle equal value clash, or some keys may "get lost in the woods":
Map<Key, Value> sortedMap = unsortedMap.entrySet().stream() // Make sure everyone finds their way home! .sorted(Entry.comparingByValue())
.collect(...); // Merge function to handle key clashes
Attention to large collections
Working with large maps? Be aware of sorting performance. For better performance, use parallel streams: .parallelStream().
Potential hiccups
Key conflation: If multiple keys have the same value, you risk losing entries. Take care to handle this in your merge function.
Type safety: Make sure that your values are Comparable or that you have a safe custom Comparator up your sleeve.