Java TreeMap

Sorted key-value storage with red-black tree implementation

🌲 What is TreeMap?

TreeMap is a sorted Map implementation that maintains keys in ascending order automatically. It uses a red-black tree structure for efficient sorted key-value storage and retrieval.


// Simple TreeMap example
TreeMap<String, Integer> scores = new TreeMap<>();
scores.put("Charlie", 85);
scores.put("Alice", 92);
scores.put("Bob", 78);
System.out.println(scores); // {Alice=92, Bob=78, Charlie=85}
                                    

TreeMap Key Features

📊

Sorted Keys

Keys are automatically sorted in natural order

TreeMap<Integer, String> months = new TreeMap<>();
months.put(12, "December");
months.put(1, "January");
months.put(6, "June");
// Order: {1=January, 6=June, 12=December}
🎯

Range Operations

Get subsets of keys within ranges

TreeMap<Integer, String> grades = new TreeMap<>();
grades.put(85, "B");
grades.put(92, "A");
grades.put(78, "C");
SortedMap<Integer, String> highGrades = 
    grades.tailMap(85); // 85 and above
âš¡

Log Time Operations

O(log n) time for basic operations

TreeMap<String, Integer> map = new TreeMap<>();
map.put("key", 100);     // O(log n)
Integer val = map.get("key"); // O(log n)
map.remove("key");       // O(log n)
🚫

No Null Keys

Cannot store null keys (but null values OK)

TreeMap<String, String> map = new TreeMap<>();
map.put("key1", null);   // OK
// map.put(null, "value"); // NullPointerException!
map.put("key2", "value"); // OK

🔹 Creating and Using TreeMap

Basic TreeMap operations with automatic sorting:

import java.util.*;

public class TreeMapExample {
    public static void main(String[] args) {
        // Create TreeMap
        TreeMap<String, Double> stockPrices = new TreeMap<>();
        
        // Add stocks (notice random order)
        stockPrices.put("MSFT", 310.50);
        stockPrices.put("AAPL", 175.25);
        stockPrices.put("GOOGL", 2650.75);
        stockPrices.put("AMZN", 3200.00);
        
        // TreeMap automatically sorts by key
        System.out.println("Sorted stock prices:");
        for (Map.Entry<String, Double> entry : stockPrices.entrySet()) {
            System.out.println(entry.getKey() + ": $" + entry.getValue());
        }
        
        // Get first and last entries
        System.out.println("\nFirst stock: " + stockPrices.firstKey());
        System.out.println("Last stock: " + stockPrices.lastKey());
        
        // Get stocks starting with 'A'
        SortedMap<String, Double> aStocks = stockPrices.subMap("A", "B");
        System.out.println("Stocks starting with A: " + aStocks);
        
        // Navigation methods
        String lowerKey = stockPrices.lowerKey("GOOGL");
        String higherKey = stockPrices.higherKey("GOOGL");
        System.out.println("Stock before GOOGL: " + lowerKey);
        System.out.println("Stock after GOOGL: " + higherKey);
    }
}

Output:

Sorted stock prices:

AAPL: $175.25

AMZN: $3200.0

GOOGL: $2650.75

MSFT: $310.5


First stock: AAPL

Last stock: MSFT

Stocks starting with A: {AAPL=175.25, AMZN=3200.0}

Stock before GOOGL: AMZN

Stock after GOOGL: MSFT

🔹 Custom Sorting with Comparator

Use custom Comparator for different sorting orders:

// Sort by string length instead of alphabetical order
TreeMap<String, Integer> wordLengthMap = new TreeMap<>(
    Comparator.comparing(String::length).thenComparing(String::compareTo)
);

wordLengthMap.put("elephant", 8);
wordLengthMap.put("cat", 3);
wordLengthMap.put("dog", 3);
wordLengthMap.put("butterfly", 9);

System.out.println("Sorted by length then alphabetically:");
wordLengthMap.forEach((word, length) -> 
    System.out.println(word + " (" + length + " letters)"));

// Reverse order TreeMap
TreeMap<Integer, String> reverseMap = new TreeMap<>(Collections.reverseOrder());
reverseMap.put(1, "First");
reverseMap.put(2, "Second");
reverseMap.put(3, "Third");

System.out.println("\nReverse order: " + reverseMap);

// Custom object sorting
class Student {
    String name;
    int grade;
    
    Student(String name, int grade) {
        this.name = name;
        this.grade = grade;
    }
    
    @Override
    public String toString() {
        return name + "(" + grade + ")";
    }
}

TreeMap<Student, String> studentMap = new TreeMap<>(
    Comparator.comparing((Student s) -> s.grade).reversed()
);

studentMap.put(new Student("Alice", 85), "Math");
studentMap.put(new Student("Bob", 92), "Science");
studentMap.put(new Student("Charlie", 78), "History");

System.out.println("\nStudents by grade (highest first):");
studentMap.forEach((student, subject) -> 
    System.out.println(student + " studies " + subject));

Output:

Sorted by length then alphabetically:

cat (3 letters)

dog (3 letters)

elephant (8 letters)

butterfly (9 letters)


Reverse order: {3=Third, 2=Second, 1=First}


Students by grade (highest first):

Bob(92) studies Science

Alice(85) studies Math

Charlie(78) studies History

🔹 TreeMap Navigation Methods

Powerful navigation methods for sorted data:

TreeMap<Integer, String> timeline = new TreeMap<>();
timeline.put(2020, "Pandemic starts");
timeline.put(2021, "Vaccines available");
timeline.put(2022, "Recovery begins");
timeline.put(2023, "New normal");
timeline.put(2024, "Future plans");

// Navigation methods
System.out.println("First entry: " + timeline.firstEntry());
System.out.println("Last entry: " + timeline.lastEntry());

// Floor and ceiling (closest matches)
System.out.println("Floor of 2021.5: " + timeline.floorEntry(2021)); // ≤ 2021.5
System.out.println("Ceiling of 2021.5: " + timeline.ceilingEntry(2022)); // ≥ 2021.5

// Lower and higher (strict comparisons)
System.out.println("Lower than 2022: " + timeline.lowerEntry(2022)); // < 2022
System.out.println("Higher than 2022: " + timeline.higherEntry(2022)); // > 2022

// Range views
SortedMap<Integer, String> earlyYears = timeline.headMap(2022); // < 2022
SortedMap<Integer, String> laterYears = timeline.tailMap(2022); // ≥ 2022
SortedMap<Integer, String> middleYears = timeline.subMap(2021, 2024); // 2021 ≤ x < 2024

System.out.println("Early years: " + earlyYears);
System.out.println("Later years: " + laterYears);
System.out.println("Middle years: " + middleYears);

// Poll operations (remove and return)
Map.Entry<Integer, String> firstRemoved = timeline.pollFirstEntry();
Map.Entry<Integer, String> lastRemoved = timeline.pollLastEntry();
System.out.println("Removed first: " + firstRemoved);
System.out.println("Removed last: " + lastRemoved);
System.out.println("Remaining: " + timeline);

Output:

First entry: 2020=Pandemic starts

Last entry: 2024=Future plans

Floor of 2021.5: 2021=Vaccines available

Ceiling of 2021.5: 2022=Recovery begins

Lower than 2022: 2021=Vaccines available

Higher than 2022: 2023=New normal

Early years: {2020=Pandemic starts, 2021=Vaccines available}

Later years: {2022=Recovery begins, 2023=New normal, 2024=Future plans}

Middle years: {2021=Vaccines available, 2022=Recovery begins, 2023=New normal}

🧠 Test Your Knowledge

What happens to the order of keys when you add them to a TreeMap?