DEV Community

realNameHidden
realNameHidden

Posted on

Java’s TreeMap.tailMap() Method Explained

Understanding TreeMap.tailMap() in Detail

The TreeMap.tailMap() method in Java provides a powerful way to work with subsets of a TreeMap where the keys are greater than or equal to a specified key. It's an essential method for range-based operations on sorted maps, especially when the data is ordered and needs partial access.

Method Variants

Default (Inclusive by Default):

SortedMap<K, V> tailMap(K fromKey)

Enter fullscreen mode Exit fullscreen mode

fromKey: The starting key for the tail view (inclusive).

Returns a view of the map with keys >= fromKey.

With Inclusivity Option:

NavigableMap<K, V> tailMap(K fromKey, boolean inclusive)

Enter fullscreen mode Exit fullscreen mode

fromKey: The starting key.
inclusive: If true, includes fromKey; otherwise, excludes it.
Returns a view of the map with keys >= (or >) fromKey based on inclusive.

Core Characteristics

Dynamic View:

The returned map is not a copy but a view, meaning changes in the original TreeMap reflect in the tail map, and vice versa.

Ordering:

The elements in the tail map are ordered based on the comparator used in the original TreeMap or natural ordering if no comparator is provided.

Edge Cases:

Handles cases where:
fromKey is smaller, equal to, or larger than the smallest/largest keys.
The map is empty or contains keys not matching fromKey.

**Scenarios and Examples

  1. Basic Usage**
import java.util.*;

public class BasicTailMapExample {
    public static void main(String[] args) {
        TreeMap<Integer, String> map = new TreeMap<>();
        map.put(1, "A");
        map.put(2, "B");
        map.put(3, "C");
        map.put(4, "D");

        // Tail map from key 2 (inclusive)
        SortedMap<Integer, String> tailMap = map.tailMap(2);
        System.out.println("TailMap: " + tailMap);
    }
}

Enter fullscreen mode Exit fullscreen mode

Output:

TailMap: {2=B, 3=C, 4=D}

Enter fullscreen mode Exit fullscreen mode

2. Using the Inclusive Option

import java.util.*;

public class TailMapInclusiveExample {
    public static void main(String[] args) {
        TreeMap<Integer, String> map = new TreeMap<>();
        map.put(10, "X");
        map.put(20, "Y");
        map.put(30, "Z");

        // Tail map excluding 20
        NavigableMap<Integer, String> tailMap = map.tailMap(20, false);
        System.out.println("TailMap (exclusive): " + tailMap);
    }
}

Enter fullscreen mode Exit fullscreen mode

Output:

TailMap (exclusive): {30=Z}

Enter fullscreen mode Exit fullscreen mode

3. Modifications to the Original Map

import java.util.*;

public class TailMapModificationExample {
    public static void main(String[] args) {
        TreeMap<Integer, String> map = new TreeMap<>();
        map.put(1, "One");
        map.put(2, "Two");
        map.put(3, "Three");

        SortedMap<Integer, String> tailMap = map.tailMap(2);
        System.out.println("Original TailMap: " + tailMap);

        // Modify original map
        map.put(4, "Four");
        map.remove(2);

        System.out.println("Modified Original Map: " + map);
        System.out.println("Updated TailMap: " + tailMap);
    }
}

Enter fullscreen mode Exit fullscreen mode

Output:

Original TailMap: {2=Two, 3=Three}
Modified Original Map: {1=One, 3=Three, 4=Four}
Updated TailMap: {3=Three, 4=Four}

Enter fullscreen mode Exit fullscreen mode

4. Handling Non-Existing Keys

If the fromKey does not exist, the map starts from the next higher key.

import java.util.*;

public class NonExistingKeyExample {
    public static void main(String[] args) {
        TreeMap<Integer, String> map = new TreeMap<>();
        map.put(5, "A");
        map.put(15, "B");
        map.put(25, "C");

        // Tail map from non-existing key 20
        SortedMap<Integer, String> tailMap = map.tailMap(20);
        System.out.println("TailMap from 20: " + tailMap);
    }
}

Enter fullscreen mode Exit fullscreen mode

output :

TailMap from 20: {25=C}

Enter fullscreen mode Exit fullscreen mode

5. Empty Tail Map
If fromKey is greater than the largest key, the tail map is empty.

import java.util.*;

public class EmptyTailMapExample {
    public static void main(String[] args) {
        TreeMap<Integer, String> map = new TreeMap<>();
        map.put(10, "Ten");

        // Tail map from key greater than all keys
        SortedMap<Integer, String> tailMap = map.tailMap(20);
        System.out.println("Empty TailMap: " + tailMap);
    }
}

Enter fullscreen mode Exit fullscreen mode

Output:

Empty TailMap: {}

Enter fullscreen mode Exit fullscreen mode

6. NullPointerException

If the TreeMap uses natural ordering and a null key is passed, a NullPointerException is thrown.

import java.util.*;

public class NullKeyExample {
    public static void main(String[] args) {
        TreeMap<Integer, String> map = new TreeMap<>();
        map.put(1, "A");

        try {
            map.tailMap(null);
        } catch (NullPointerException e) {
            System.out.println("Exception: " + e);
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

Output:

Exception: java.lang.NullPointerException

Enter fullscreen mode Exit fullscreen mode

When to Use TreeMap.tailMap()

Range Queries: Retrieve all elements greater than or equal to a threshold key.

Dynamic Views: Filter and work with a live subset of the map.
Data Streaming: Efficiently stream data starting from a specific key in sorted order.

By combining it with other TreeMap methods like headMap() and subMap(), tailMap() enables flexible and precise manipulation of sorted data structures.

Top comments (0)