Stream the entries, sort them with Map.Entry.comparingByValue(), and collect into a LinkedHashMap so the order sticks: map.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a, LinkedHashMap::new)). For descending order, pass Comparator.reverseOrder() to comparingByValue.
A HashMap has no order you can change, and a TreeMap only ever orders by its keys, so no Map sorts itself by value. The answer is to sort the map's entries and put them into a map that remembers the order you insert things in, which is what LinkedHashMap does. Everything here is plain Java SE: Map.Entry.comparingByValue() and streams arrived in Java 8, and the page notes where a newer method needs Java 16 or 21. It also covers descending order, ties, sorting into a list, and the difference between HashMap, LinkedHashMap and TreeMap. Each example runs on this page: hit Run, then edit the code and run it again.
1Stream the entries into a LinkedHashMapRecommended
entrySet().stream() gives you the key/value pairs, and sorted(Map.Entry.comparingByValue()) orders them by value. The part people get wrong is the collector. You need the four-argument Collectors.toMap(keyMapper, valueMapper, mergeFunction, mapFactory), because only that form lets you pass LinkedHashMap::new as the map to fill. The merge function is required by the signature; it only runs on duplicate keys, which an entrySet() never has.
Output
Prints {java=64, go=78, rust=85, python=92}, then [java, go, rust, python], then HashMap. That last line is the classic bug: the two-argument toMap sorts the entries correctly and then drops them into a HashMap, whose iteration order has nothing to do with the sort. The same applies to Collectors.toMap with any map factory other than LinkedHashMap::new. Stream.toList() needs Java 16+; on Java 8 to 15 write .collect(Collectors.toList()). The sorted map is a new object, so the original scores is unchanged. To loop over the result, see iterate over a map.
2Descending order and tie-breaks
There are three equivalent ways to put the highest value first: Map.Entry.comparingByValue(Comparator.reverseOrder()), Collections.reverseOrder(Map.Entry.comparingByValue()), and .reversed() on the comparator. The last one needs a type witness, Map.Entry.<String, Integer>comparingByValue(), or it doesn't compile. When two values tie, Stream.sorted() is stable, so tied entries keep the order they had in the source map. To make the order explicit instead, chain .thenComparing(Map.Entry.comparingByKey()).
Output
The first three lines all print {raj=5, kim=5, dana=3, bea=3, ana=1}: raj before kim and dana before bea, because that is the order they were inserted. The tie-broken line prints {kim=5, raj=5, bea=3, dana=3, ana=1}, alphabetical within each score. Rely on stability only when the source has a defined order; with a HashMap as the source, the order of ties is whatever order the hash table happens to iterate in, so add the tie-breaker. Keep the sortBy helper if you sort maps often: it turns every variation on this page into a single comparator.
3Sort into a List of entries, and take the top N
Often you don't need a map back at all, just the pairs in order. Copy the entries into an ArrayList and sort it in place with List.sort, which is also the pre-stream way to do this. For a leaderboard or a word-frequency report, the stream version adds .limit(n) after the sort to keep only the top n.
Output
Prints [the=41, java=23, code=17, ship=12, run=9], then one aligned line per word (the 41 down to run 9), then top 3: [the=41, java=23, code=17] and the .. run. getFirst() and getLast() are Java 21+; before that, use get(0) and get(entries.size() - 1). Before Java 8 the same sort was Collections.sort(entries, new Comparator<…>() { … }) with a compare method that returned b.getValue().compareTo(a.getValue()); comparingByValue replaces all of that. For a list of objects rather than map entries, see sort a list of objects by property.
4Which should you use?
| Method | Gives you | Java | Best for |
|---|---|---|---|
| stream().sorted(comparingByValue()) + toMap(…, LinkedHashMap::new) | A Map in value order | 8+ | Almost everything |
| comparingByValue(Comparator.reverseOrder()) | Descending | 8+ | Leaderboards, highest first |
| .thenComparing(Map.Entry.comparingByKey()) | A fixed order for ties | 8+ | Output that must never change between runs |
| new ArrayList<>(map.entrySet()) + list.sort(…) | A List of entries | 8+ | Reports, index access, no map needed |
| stream().sorted(…).limit(n) | The top N only | 8+ | Top 10 lists, word counts |
| new TreeMap<>(map) | Sorted by key | Any | Key order, never value order |
5Why a TreeMap sorts by key, not value
A TreeMap keeps its entries sorted by key, using the keys' natural order or a Comparator of keys. That makes new TreeMap<>(map) the one-line way to sort a map by key. A popular old answer tries to bend it into sorting by value, with a comparator that looks each key's value up in the original map. It breaks as soon as two values are equal: the TreeMap decides that two keys are the same key when the comparator returns 0, and drops one of them.
Output
Prints {apple=7, fig=3, kiwi=1, pear=3} (by key), then {pear=3, kiwi=1, fig=3, apple=7} (by key, reversed). The value-comparator TreeMap prints {kiwi=1, pear=3, apple=7} and 3 of 4 entries: fig has the same stock as pear, so the TreeMap treated it as a duplicate of pear and only updated that entry's value. It still prints fig -> 3, because get("fig") finds pear through the same comparator. A key that isn't in stock is worse: the lookup returns null and every put or get with it throws a NullPointerException. Sort the entries instead, as in section 1.
6HashMap vs LinkedHashMap vs TreeMap
These three differ only in iteration order. HashMap promises no order, and the order can change as the map grows. LinkedHashMap iterates in insertion order, which is why it is the target for a sorted result, and the answer when you want a Map that keeps insertion order. TreeMap iterates in key order and adds range methods such as headMap and firstKey. HashMap and LinkedHashMap do lookups in constant time; TreeMap takes O(log n) per get and put.
Output
Prints {zulu=26, alpha=100, mike=13}: alpha got its new value but stayed second. The TreeMap prints {alpha=100, mike=13, zulu=26} and alpha {alpha=100, mike=13}. true true shows that equals compares contents and ignores order, so all three maps are equal. The Java 21 lines print echo=5 mike=13 and {mike=13, alpha=100, zulu=26, echo=5}, and the access-order map prints {b=2, c=3, a=1} because reading a moved it to the end. The HashMap itself is never printed here on purpose: its order is an implementation detail. The same goes for Map.of(…), whose iteration order changes from one run of the JVM to the next.
Frequently asked questions
How do I sort a HashMap by value in Java?
You can’t reorder a HashMap itself, so build a new map: map.entrySet().stream().sorted(Map.Entry.comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a, LinkedHashMap::new)). The LinkedHashMap keeps the entries in the order the sorted stream inserts them. Collecting with the two-argument toMap gives you a HashMap again and loses the order.
Why does Map.Entry.comparingByValue().reversed() not compile?
Java can’t infer the key and value types through the .reversed() call, so it fails with incompatible types: java.util.Comparator<java.util.Map.Entry<java.lang.Object,V>> cannot be converted to .... Give it a type witness, Map.Entry.<String, Integer>comparingByValue().reversed(), or avoid the problem with Map.Entry.comparingByValue(Comparator.reverseOrder()) or Collections.reverseOrder(Map.Entry.comparingByValue()).
What is the difference between HashMap, LinkedHashMap and TreeMap?
Iteration order. HashMap promises no order at all. LinkedHashMap iterates in insertion order, or in access order if you construct it with accessOrder = true. TreeMap iterates in key order and adds navigation methods such as firstKey, headMap and ceilingKey. HashMap and LinkedHashMap have constant-time get and put and allow a null key; TreeMap is O(log n) and rejects null keys under natural ordering.
Which Java Map keeps insertion order?
LinkedHashMap. Iteration follows the order keys were first inserted, and putting an existing key again updates its value without moving it. Since Java 21 it also implements SequencedMap, which adds firstEntry(), lastEntry(), putFirst(), putLast() and reversed(). HashMap, Map.of(...) and HashSet make no order promise.
How do I sort a map by a field of its values?
Pass a comparator for the value type to comparingByValue. With a Map<String, Person> where Person is a record with an age, sorted(Map.Entry.comparingByValue(Comparator.comparingInt(Person::age))) orders the entries youngest first, and the rest of the stream is unchanged. A map of u1 Grace 45, u2 Ada 36 and u3 Linus 29 comes out as {u3=Person[name=Linus, age=29], u2=Person[name=Ada, age=36], u1=Person[name=Grace, age=45]}.
What happens if the map has null values?
Map.Entry.comparingByValue() throws a NullPointerException on a null value, so use Map.Entry.comparingByValue(Comparator.nullsLast(Comparator.naturalOrder())). Collectors.toMap also throws a NullPointerException on a null value, so fill the LinkedHashMap yourself: .forEachOrdered(e -> result.put(e.getKey(), e.getValue())). For {x=2, y=null, z=1} that gives {z=1, x=2, y=null}.