Question

How to Sort a Map by Value in Java

javasortingdictionarycollections

Question

I need to sort a Map<Key, Value> by its values in Java.

Because the values are not unique, I have been converting the keySet() into an array and sorting that array with a custom comparator that compares the values associated with each key.

Is there a simpler or more idiomatic way to sort a map by value?

For example, the goal is something like this:

Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 90);
scores.put("Bob", 75);
scores.put("Charlie", 90);
scores.put("Diana", 82);

I want the entries ordered by the Integer values.

Short Answer

By the end of this page, you will understand how to sort a Java Map by its values, why maps are not automatically value-ordered, and the common patterns developers use to create a sorted result. You will also learn when to use List<Map.Entry<K,V>>, Stream, and LinkedHashMap to preserve the sorted order.

Concept

In Java, a Map stores key-value pairs, but most map implementations do not keep entries sorted by value.

Why this happens

Different Map types have different ordering rules:

  • HashMap does not guarantee any order.
  • TreeMap sorts by key, not by value.
  • LinkedHashMap keeps insertion order.

So if you want a map sorted by value, you usually do not sort the map directly. Instead, you:

  1. Get the map entries.
  2. Sort the entries by value.
  3. Put them into an ordered structure, usually a LinkedHashMap.

Why this matters

Sorting by value is common when you want to:

  • show rankings
  • display counts from highest to lowest
  • sort configuration or report data by importance
  • produce ordered output for users or logs

Important idea

A Map itself is not really a "sortable list." It is a lookup structure. To sort it by value, you temporarily treat its entries like a collection that can be sorted.

What about duplicate values?

Duplicate values are completely fine when sorting by value. They only matter if you need a stable tie-breaker. For example, if two entries both have value 90, you may also want to sort by key so the result is predictable.

Comparator<Map.Entry<String, Integer>> byValueThenKey =
    Map.Entry.<String, Integer>comparingByValue()
             .thenComparing(Map.Entry.comparingByKey());

This is the idiomatic way to handle equal values cleanly.

Mental Model

Think of a Map like a set of labeled folders in a cabinet:

  • the key is the folder label
  • the value is what is written inside the folder

A cabinet like HashMap is great for quickly finding a folder by label, but it is not arranged by what is written inside each folder.

If you want folders ordered by their contents, you take all folders out, line them up on a table, sort them by the inside value, and then place them into a cabinet that keeps that new order, such as a LinkedHashMap.

So the mental model is:

  • Map = fast lookup
  • List of entries = sortable view
  • LinkedHashMap = preserves the sorted result
Take Quiz

Syntax and Examples

Basic approach: sort entries by value

Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 90);
scores.put("Bob", 75);
scores.put("Charlie", 90);
scores.put("Diana", 82);

List<Map.Entry<String, Integer>> entries = new ArrayList<>(scores.entrySet());
entries.sort(Map.Entry.comparingByValue());

for (Map.Entry<String, Integer> entry : entries) {
    System.out.println(entry.getKey() + " -> " + entry.getValue());
}

What this does

  • entrySet() gives you all key-value pairs.
  • new ArrayList<>(...) makes them sortable.
  • entries.sort(...) sorts the list by value.

This is often the simplest approach if you only need sorted output.

Creating a new map that keeps the sorted order

Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 90);
scores.put("Bob", 75);
scores.put("Charlie", 90);
scores.put("Diana", 82);

Map<String, Integer> sorted = new LinkedHashMap<>();

scores.entrySet()
      .stream()
      .sorted(Map.Entry.comparingByValue())
      .forEachOrdered(entry -> sorted.put(entry.getKey(), entry.getValue()));

System.out.println(sorted);

Why LinkedHashMap?

Because it preserves insertion order. After sorting the stream, entries are inserted in sorted order, and LinkedHashMap keeps that order.

Sorting in descending order

Map<String, Integer> sortedDescending = new LinkedHashMap<>();

scores.entrySet()
      .stream()
      .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
      .forEachOrdered(entry -> sortedDescending.put(entry.getKey(), entry.getValue()));

Sorting by value, then by key

This is useful when values are equal.

Map<String, Integer> sorted = new LinkedHashMap<>();

scores.entrySet()
      .stream()
      .sorted(
          Map.Entry.<String, Integer>comparingByValue()
              .thenComparing(Map.Entry.comparingByKey())
      )
      .forEachOrdered(entry -> sorted.put(entry.getKey(), entry.getValue()));

This gives predictable ordering for duplicate values.

Step by Step Execution

Consider this example:

Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 90);
scores.put("Bob", 75);
scores.put("Charlie", 90);
scores.put("Diana", 82);

List<Map.Entry<String, Integer>> entries = new ArrayList<>(scores.entrySet());
entries.sort(
    Map.Entry.<String, Integer>comparingByValue()
        .thenComparing(Map.Entry.comparingByKey())
);

for (Map.Entry<String, Integer> entry : entries) {
    System.out.println(entry.getKey() + " -> " + entry.getValue());
}

Step by step

1. Create the map

The map contains these pairs:

  • Alice -> 90
  • Bob -> 75
  • Charlie -> 90
  • Diana -> 82

Because this is a HashMap, the internal order is not guaranteed.

2. Convert entries to a list

List<Map.Entry<String, Integer>> entries = new ArrayList<>(scores.entrySet());

Now you have a list of entries that can be sorted.

3. Sort by value, then key

entries.sort(
    Map.Entry.<String, Integer>comparingByValue()
        .thenComparing(Map.Entry.comparingByKey())
);

The comparator works like this:

  • compare values first
  • if two values are equal, compare keys

So the order becomes:

  1. Bob -> 75
  2. Diana -> 82
  3. Alice -> 90
  4. Charlie -> 90

Alice and Charlie both have 90, so the key is used as a tie-breaker.

4. Print the sorted entries

The loop prints the entries in the sorted order.

Final output

Bob -> 75
Diana -> 82
Alice -> 90
Charlie -> 90

Real World Use Cases

Sorting a map by value appears often in real programs.

Ranking and leaderboards

Map<String, Integer> playerScores = Map.of(
    "Ana", 1200,
    "Ben", 950,
    "Cara", 1200,
    "Dan", 870
);

You may want to display highest scores first.

Counting frequencies

If you count how many times words appear, you might store:

Map<String, Integer> wordCounts = new HashMap<>();

Then sort by count to show the most common words.

Reporting and analytics

You may have category totals like:

  • Books -> 340
  • Games -> 525
  • Music -> 210

Sorting by value helps produce readable reports.

API response formatting

Sometimes backend code calculates scores, priorities, or usage metrics in a map, then sorts them before returning a response.

Configuration and diagnostics

Developers may sort metrics or error counts so the most important items appear first in logs or debug output.

Take Quiz

Real Codebase Usage

In real projects, developers usually do not try to force a normal Map to become value-sorted forever. Instead, they use one of these patterns.

Pattern 1: Sort when presenting data

Keep data in a HashMap for fast lookup, and only sort when displaying or exporting it.

List<Map.Entry<String, Integer>> sortedEntries = new ArrayList<>(scores.entrySet());
sortedEntries.sort(Map.Entry.comparingByValue());

This is common in services and reporting code.

Pattern 2: Build a LinkedHashMap for ordered output

When the final result must behave like a map but still preserve sorted order, developers collect into a LinkedHashMap.

Map<String, Integer> sorted = scores.entrySet()
    .stream()
    .sorted(Map.Entry.comparingByValue())
    .collect(
        LinkedHashMap::new,
        (map, entry) -> map.put(entry.getKey(), entry.getValue()),
        LinkedHashMap::putAll
    );

Pattern 3: Add tie-breakers for deterministic output

In production code, predictable output matters.

.sorted(
    Map.Entry.<String, Integer>comparingByValue()
        .thenComparing(Map.Entry.comparingByKey())
)

Without a tie-breaker, equal values may appear in an unspecified relative order depending on source ordering.

Pattern 4: Validate null handling

If values may be null, developers usually define how nulls should be ordered.

Comparator<Map.Entry<String, Integer>> cmp =
    Comparator.comparing(
        Map.Entry::getValue,
        Comparator.nullsLast(Integer::compareTo)
    );

Pattern 5: Use descending order for top-N reports

List<Map.Entry<String, Integer>> topItems = scores.entrySet()
    .stream()
    .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
    .limit(10)
    .toList();

This is common for dashboards, leaderboards, and analytics.

Common Mistakes

Mistake 1: Expecting HashMap to stay sorted

Broken idea:

Map<String, Integer> map = new HashMap<>();
// sort somehow
System.out.println(map);

A HashMap does not preserve sorted order.

Fix

Use:

  • a sorted List<Map.Entry<K,V>>, or
  • a LinkedHashMap to preserve the sorted insertion order

Mistake 2: Using TreeMap to sort by value

Broken idea:

Map<String, Integer> map = new TreeMap<>();

TreeMap sorts by key, not value.

Fix

Sort entrySet() using a comparator based on getValue().

Mistake 3: Ignoring duplicate values

If multiple entries have the same value, the order among them may not be what you expect.

entries.sort(Map.Entry.comparingByValue());

This sorts by value only.

Fix

Add a secondary comparison:

entries.sort(
    Map.Entry.<String, Integer>comparingByValue()
        .thenComparing(Map.Entry.comparingByKey())
);

Mistake 4: Assuming the original map changes order

Broken expectation:

List<Map.Entry<String, Integer>> entries = new ArrayList<>(map.entrySet());
entries.sort(Map.Entry.comparingByValue());
// expecting map itself to now be sorted

Sorting the list does not change the original map's iteration order.

Fix

Create a new ordered map if needed.

Mistake 5: Not handling null values

Broken code:

entries.sort(Map.Entry.comparingByValue());

This may fail if some values are null.

Fix

Use a null-safe comparator:

entries.sort(
    Comparator.comparing(
        Map.Entry<String, Integer>::getValue,
        Comparator.nullsLast(Integer::compareTo)
    )
);

Mistake 6: Sorting keys and repeatedly looking up values unnecessarily

Your original approach of sorting keys can work, but it is usually less direct than sorting entries.

Less idiomatic approach:

List<String> keys = new ArrayList<>(scores.keySet());
keys.sort(Comparator.comparing(scores::get));

Better approach

List<Map.Entry<String, Integer>> entries = new ArrayList<>(scores.entrySet());
entries.sort(Map.Entry.comparingByValue());

This works directly with key-value pairs and is easier to read.

Comparisons

Common ways to get a map sorted by value

ApproachWhat it sortsKeeps map structure?Preserves sorted order after sorting?Best for
List<Map.Entry<K,V>> + sort()EntriesNoYes, in the listDisplaying or iterating sorted results
Stream + sorted() + LinkedHashMapEntriesYesYesReturning an ordered map
Sort keySet() using map.get(key)KeysNoYes, in the key listWorks, but less direct
TreeMapKeysYesYes, by key onlyWhen key ordering is needed

entrySet() sorting vs keySet() sorting

OptionProsCons
Sort entrySet()Direct, readable, idiomaticRequires working with entries
Sort keySet()Useful if you only need keysIndirect; value lookup happens through keys

LinkedHashMap vs TreeMap

Map TypeOrdering Rule
HashMapNo guaranteed order
LinkedHashMapInsertion order
TreeMapSorted by key

If you sort by value and want to keep that order in a map, LinkedHashMap is usually the correct choice.

Take Quiz

Cheat Sheet

Quick reference

Sort map entries by value

List<Map.Entry<K, V>> entries = new ArrayList<>(map.entrySet());
entries.sort(Map.Entry.comparingByValue());

Sort by value descending

entries.sort(Map.Entry.<K, V>comparingByValue().reversed());

Sort by value, then key

entries.sort(
    Map.Entry.<K, V>comparingByValue()
        .thenComparing(Map.Entry.comparingByKey())
);

Build a LinkedHashMap with sorted order

Map<K, V> sorted = new LinkedHashMap<>();
map.entrySet().stream()
   .sorted(Map.Entry.comparingByValue())
   .forEachOrdered(e -> sorted.put(e.getKey(), e.getValue()));

Null-safe value sorting

entries.sort(
    Comparator.comparing(
        Map.Entry<K, V>::getValue,
        Comparator.nullsLast(Comparator.naturalOrder())
    )
);

Key rules

  • HashMap is not sorted.
  • TreeMap sorts by key, not value.
  • To sort by value, sort entrySet().
  • To preserve sorted order in a map, use LinkedHashMap.
  • Add thenComparing(...) if equal values need stable ordering.

FAQ

Can a Java Map be sorted directly by value?

Not usually. Most Map implementations are not designed to maintain value-based order. The common solution is to sort the entries and store the result in a List or LinkedHashMap.

Should I use TreeMap to sort by value?

No. TreeMap sorts by key only.

What happens if two entries have the same value?

They can both appear in the result. If you want predictable ordering, add a secondary sort such as thenComparing(Map.Entry.comparingByKey()).

What is the easiest way to sort a map by value in Java?

A simple and common way is:

List<Map.Entry<K, V>> entries = new ArrayList<>(map.entrySet());
entries.sort(Map.Entry.comparingByValue());

How do I keep the sorted result as a map?

Insert the sorted entries into a LinkedHashMap, which preserves insertion order.

Can I sort a map by value in descending order?

Yes:

.sorted(Map.Entry.<K, V>comparingByValue().reversed())

Is sorting keySet() by map.get(key) wrong?

No, it works. But sorting entrySet() is usually clearer and more idiomatic.

Take Quiz

Mini Project

Description

Create a small Java program that reads a set of product names and sales counts, then prints the products ordered by sales. This demonstrates the common real-world pattern of collecting data in a Map, sorting by value, and preserving the result in a LinkedHashMap for predictable output.

Goal

Build a program that sorts product sales by value in descending order and prints a ranked report.

Requirements

  1. Create a Map<String, Integer> containing at least five products and their sales counts.
  2. Sort the entries by sales count in descending order.
  3. Use the product name as a tie-breaker when sales counts are equal.
  4. Store the sorted result in a LinkedHashMap.
  5. Print the final ranking in order.
Take Quiz

Keep learning

Related questions

View more