Java SortedMap Interface

Introduction

The SortedMap interface in Java, part of the java.util package, is a specialized map that maintains its entries in ascending key order. This interface extends the Map interface and adds methods that provide navigation and sorted views of the map. The most commonly used implementation of SortedMap is TreeMap.

Table of Contents

  1. What is the SortedMap Interface?
  2. Common Implementations
  3. Common Methods
  4. Examples of Using the SortedMap Interface
  5. Conclusion

1. What is the SortedMap Interface?

The SortedMap interface extends the Map interface and maintains its entries sorted according to the natural ordering of the keys or by a specified comparator. This ordering is consistent with equals only if the comparator used is consistent with equals.

2. Common Implementations

  • TreeMap: A Red-Black tree-based implementation of the SortedMap interface. It provides guaranteed log(n) time cost for the basic operations (get, put, remove) and maintains the order of its keys.

3. Common Methods

  • comparator(): Returns the comparator used to order the keys in this map, or null if this map uses the natural ordering of its keys.
  • subMap(K fromKey, K toKey): Returns a view of the portion of this map whose keys range from fromKey, inclusive, to toKey, exclusive.
  • headMap(K toKey): Returns a view of the portion of this map whose keys are strictly less than toKey.
  • tailMap(K fromKey): Returns a view of the portion of this map whose keys are greater than or equal to fromKey.
  • firstKey(): Returns the first (lowest) key currently in this map.
  • lastKey(): Returns the last (highest) key currently in this map.

4. Examples of Using the SortedMap Interface

Example 1: Basic Usage with TreeMap

This example demonstrates how to use a TreeMap with the SortedMap interface.

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

public class SortedMapExample {
    public static void main(String[] args) {
        SortedMap<Integer, String> map = new TreeMap<>();

        // Adding elements to the map
        map.put(3, "Three");
        map.put(1, "One");
        map.put(4, "Four");
        map.put(2, "Two");

        // Displaying the map
        System.out.println("SortedMap: " + map);

        // Accessing the first and last keys
        System.out.println("First Key: " + map.firstKey());
        System.out.println("Last Key: " + map.lastKey());

        // Getting a subMap
        SortedMap<Integer, String> subMap = map.subMap(2, 4);
        System.out.println("SubMap from 2 to 4: " + subMap);

        // Getting a headMap
        SortedMap<Integer, String> headMap = map.headMap(3);
        System.out.println("HeadMap up to 3: " + headMap);

        // Getting a tailMap
        SortedMap<Integer, String> tailMap = map.tailMap(3);
        System.out.println("TailMap from 3: " + tailMap);
    }
}

Output:

SortedMap: {1=One, 2=Two, 3=Three, 4=Four}
First Key: 1
Last Key: 4
SubMap from 2 to 4: {2=Two, 3=Three}
HeadMap up to 3: {1=One, 2=Two}
TailMap from 3: {3=Three, 4=Four}

Example 2: Using Custom Comparator

This example shows how to use a TreeMap with a custom comparator.

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

public class CustomComparatorExample {
    public static void main(String[] args) {
        Comparator<String> reverseOrder = Comparator.reverseOrder();
        SortedMap<String, Integer> map = new TreeMap<>(reverseOrder);

        // Adding elements to the map
        map.put("Banana", 1);
        map.put("Apple", 2);
        map.put("Cherry", 3);

        // Displaying the map
        System.out.println("SortedMap with Custom Comparator: " + map);

        // Accessing the first and last keys
        System.out.println("First Key: " + map.firstKey());
        System.out.println("Last Key: " + map.lastKey());
    }
}

Output:

SortedMap with Custom Comparator: {Cherry=3, Banana=1, Apple=2}
First Key: Cherry
Last Key: Apple

Example 3: Navigating through the Map

This example demonstrates how to navigate through the SortedMap using different methods.

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

public class NavigationExample {
    public static void main(String[] args) {
        SortedMap<Integer, String> map = new TreeMap<>();

        // Adding elements to the map
        map.put(1, "One");
        map.put(2, "Two");
        map.put(3, "Three");
        map.put(4, "Four");
        map.put(5, "Five");

        // Displaying the map
        System.out.println("SortedMap: " + map);

        // Accessing elements using navigational methods
        System.out.println("HeadMap (less than 3): " + map.headMap(3));
        System.out.println("TailMap (3 and more): " + map.tailMap(3));
        System.out.println("SubMap (2 to 4): " + map.subMap(2, 4));
    }
}

Output:

SortedMap: {1=One, 2=Two, 3=Three, 4=Four, 5=Five}
HeadMap (less than 3): {1=One, 2=Two}
TailMap (3 and more): {3=Three, 4=Four, 5=Five}
SubMap (2 to 4): {2=Two, 3=Three}

Example 4: Using SortedMap with Custom Objects

This example demonstrates how to use a SortedMap with custom objects, requiring the implementation of Comparable or providing a Comparator.

import java.util.*;

public class CustomObjectSortedMapExample {
    public static void main(String[] args) {
        SortedMap<Person, Integer> map = new TreeMap<>();

        // Adding custom objects to the map
        map.put(new Person("Raj", 30), 1);
        map.put(new Person("Anita", 25), 2);
        map.put(new Person("Vikram", 35), 3);

        // Iterating over the map
        for (Map.Entry<Person, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + " => " + entry.getValue());
        }
    }
}

class Person implements Comparable<Person> {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(Person other) {
        return Integer.compare(this.age, other.age);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

Output:

Person{name='Anita', age=25} => 2
Person{name='Raj', age=30} => 1
Person{name='Vikram', age=35} => 3

5. Conclusion

The SortedMap interface in Java provides a powerful way to manage maps that maintain their entries in ascending key order. By using different implementations like TreeMap, developers can take advantage of navigational methods and custom ordering. The examples provided demonstrate common usage patterns and highlight the capabilities of the SortedMap interface.

Comments