00:00

SortedMap Interface in Java – Guide with Examples

SortedMap is a Map that keeps its entries ordered by key. It adds methods to get the first and last keys and to take range views of the map, such as "all products under ₹1,000".

It is an interface in java.util, part of the Collections Framework since JDK 1.2. Its main implementation is TreeMap. This tutorial explains every SortedMap method with examples.

1. What Is a SortedMap?

A SortedMap guarantees that its keySet(), values() and entrySet() all iterate in ascending key order. The order comes from the keys' natural ordering (Comparable) or from a Comparator supplied when the map is created.

  • Keys always sorted.
  • Endpoints: firstKey() and lastKey().
  • Range views: headMap(), tailMap() and subMap().
  • comparator() returns the comparator in use, or null for natural order.
  • Keys are compared with compareTo() or the comparator, not with equals().

2. Hierarchy and Declaration

java.util.SortedMap
public interface SortedMap<K, V> extends SequencedMap<K, V>   // Java 21+
// before Java 21: public interface SortedMap<K, V> extends Map<K, V>
Hierarchy
Map
 └─ SequencedMap (Java 21)
     └─ SortedMap
         └─ NavigableMap
             ├─ TreeMap
             └─ ConcurrentSkipListMap

3. Creating and Using a SortedMap

SortedMapBasics.java
import java.util.SortedMap;
import java.util.TreeMap;

public class SortedMapBasics {
    public static void main(String[] args) {
        SortedMap<Integer, String> rank = new TreeMap<>();
        rank.put(3, "Kiran");
        rank.put(1, "Asha");
        rank.put(2, "Ravi");

        System.out.println("Ranks:        " + rank);
        System.out.println("firstKey():   " + rank.firstKey());
        System.out.println("lastKey():    " + rank.lastKey());
        System.out.println("comparator(): " + rank.comparator());
        System.out.println("keySet():     " + rank.keySet() + "  values(): " + rank.values());
    }
}
Output
Ranks:        {1=Asha, 2=Ravi, 3=Kiran}
firstKey():   1
lastKey():    3
comparator(): null
keySet():     [1, 2, 3]  values(): [Asha, Ravi, Kiran]

The entries were added as 3, 1, 2 but come back as 1, 2, 3. comparator() returns null because the map uses the natural order of Integer.

4. SortedMap Methods

MethodDescription
K firstKey()The lowest key; throws NoSuchElementException if empty.
K lastKey()The highest key; throws NoSuchElementException if empty.
SortedMap<K,V> headMap(K toKey)View of entries with keys strictly less than toKey.
SortedMap<K,V> tailMap(K fromKey)View of entries with keys greater than or equal to fromKey.
SortedMap<K,V> subMap(K fromKey, K toKey)View from fromKey (inclusive) to toKey (exclusive).
Comparator<? super K> comparator()The comparator, or null for natural ordering.
keySet(), values(), entrySet()Views that iterate in ascending key order.
firstEntry(), lastEntry(), pollFirstEntry(), pollLastEntry(), reversed()Sequenced methods (Java 21).

5. Range Views: headMap, tailMap and subMap

Here a price list is split into ranges. Note that views are live in both directions:

SortedMapRanges.java
import java.util.SortedMap;
import java.util.TreeMap;

public class SortedMapRanges {
    public static void main(String[] args) {
        SortedMap<Integer, String> products = new TreeMap<>();   // price -> product
        products.put(199, "cable");
        products.put(499, "mouse");
        products.put(999, "keyboard");
        products.put(2499, "headphones");
        products.put(15999, "monitor");

        System.out.println("Under 1000:      " + products.headMap(1000));
        System.out.println("1000 and above:  " + products.tailMap(1000));
        System.out.println("400 to 2999:     " + products.subMap(400, 3000));

        SortedMap<Integer, String> cheap = products.headMap(1000);   // live view
        products.put(299, "charger");
        System.out.println("Cheap view now:  " + cheap);

        cheap.remove(199);                                            // removes from products too
        System.out.println("All products:    " + products);
    }
}
Output
Under 1000:      {199=cable, 499=mouse, 999=keyboard}
1000 and above:  {2499=headphones, 15999=monitor}
400 to 2999:     {499=mouse, 999=keyboard, 2499=headphones}
Cheap view now:  {199=cable, 299=charger, 499=mouse, 999=keyboard}
All products:    {299=charger, 499=mouse, 999=keyboard, 2499=headphones, 15999=monitor}
  • The lower bound is inclusive, the upper bound exclusive.
  • The charger added to the full map appeared in the cheap view.
  • Removing 199 through the view removed the cable from the full map.
  • Putting a key outside a view's range through that view throws IllegalArgumentException.

6. Custom Key Order with a Comparator

Sorting strings as text puts "1.10" before "1.2", which is wrong for version numbers. A comparator that compares the numeric parts fixes it:

VersionOrder.java
import java.util.Comparator;
import java.util.SortedMap;
import java.util.TreeMap;

public class VersionOrder {
    // Compare "1.10" and "1.9" by their numeric parts, not as text
    static final Comparator<String> BY_VERSION = (a, b) -> {
        String[] x = a.split("\\."), y = b.split("\\.");
        for (int i = 0; i < Math.max(x.length, y.length); i++) {
            int p = i < x.length ? Integer.parseInt(x[i]) : 0;
            int q = i < y.length ? Integer.parseInt(y[i]) : 0;
            if (p != q) return Integer.compare(p, q);
        }
        return 0;
    };

    public static void main(String[] args) {
        String[] versions = {"1.10", "1.2", "1.9", "2.0", "1.2.1"};

        SortedMap<String, String> asText = new TreeMap<>();
        SortedMap<String, String> asVersion = new TreeMap<>(BY_VERSION);
        for (String v : versions) {
            asText.put(v, "release");
            asVersion.put(v, "release");
        }
        System.out.println("Text order:    " + asText.keySet());
        System.out.println("Version order: " + asVersion.keySet());
        System.out.println("Latest:        " + asVersion.lastKey());
    }
}
Output
Text order:    [1.10, 1.2, 1.2.1, 1.9, 2.0]
Version order: [1.2, 1.2.1, 1.9, 1.10, 2.0]
Latest:        2.0

The comparator treats "1.2" and "1.2.0" as equal, so in this map they would be the same key. Design comparators carefully, because they decide what a duplicate key is.

7. Java 21: First, Last and Reversed

Since Java 21, SortedMap extends SequencedMap. Methods that read or remove at the ends work; methods that insert at a chosen end do not, because the sort order decides each key's position.

SequencedSortedMap.java
import java.util.SortedMap;
import java.util.TreeMap;

public class SequencedSortedMap {
    public static void main(String[] args) {
        SortedMap<String, Integer> scores = new TreeMap<>();
        scores.put("delta", 4);
        scores.put("alpha", 1);
        scores.put("charlie", 3);

        // Java 21: SortedMap is a SequencedMap
        System.out.println("firstEntry():     " + scores.firstEntry());
        System.out.println("lastEntry():      " + scores.lastEntry());
        System.out.println("reversed():       " + scores.reversed());
        System.out.println("pollFirstEntry(): " + scores.pollFirstEntry() + " -> " + scores);

        try {
            scores.putFirst("zulu", 26);     // position is decided by the sort order
        } catch (UnsupportedOperationException e) {
            System.out.println("putFirst(): UnsupportedOperationException");
        }
    }
}
Output
firstEntry():     alpha=1
lastEntry():      delta=4
reversed():       {delta=4, charlie=3, alpha=1}
pollFirstEntry(): alpha=1 -> {charlie=3, delta=4}
putFirst(): UnsupportedOperationException

8. Implementations

ClassStructureThread-safeNotes
TreeMapRed-black treeNoThe usual choice; O(log n).
ConcurrentSkipListMapSkip listYesConcurrent sorted map.
Collections.unmodifiableSortedMap()WrapperRead-onlyRejects changes.
Collections.synchronizedSortedMap()WrapperYes (locks)Lock it manually while iterating.

9. SortedMap vs NavigableMap

NavigableMap (Java 6) extends SortedMap with nearest-key lookups and more flexible ranges:

NeedSortedMapNavigableMap
First/last keyfirstKey(), lastKey()Same, plus firstEntry(), pollFirstEntry()…
Nearest keyNofloorKey(), ceilingKey(), lowerKey(), higherKey()
Inclusive/exclusive boundsFixedChosen per bound
Reverse viewreversed() (Java 21)descendingMap()

10. Rules for Keys

  • With natural ordering, keys must implement Comparable, otherwise ClassCastException.
  • null keys are not allowed with natural ordering.
  • Keys that compare as 0 are the same key, even if equals() disagrees.
  • Do not modify a key's sort fields while it is in the map.

11. Summary

  • SortedMap keeps entries in ascending key order.
  • It adds firstKey(), lastKey(), headMap(), tailMap(), subMap() and comparator().
  • Range views are live, inclusive at the start and exclusive at the end.
  • TreeMap is the main implementation; ConcurrentSkipListMap is the concurrent one.
  • NavigableMap extends it with nearest-key methods and flexible ranges.

Related Tutorials

Reference: Java SE 21 API: java.util.SortedMap