Java NavigableMap Interface
The NavigableMap
interface in Java extends the SortedMap
interface and provides additional functionality for navigating the entries in a sorted map. It introduces methods for searching for entries relative to a given key and allows you to navigate the map in various ways—either upwards or downwards, providing a more powerful and flexible way to interact with sorted key-value pairs.
While SortedMap
gives basic sorting and range methods, NavigableMap
adds enhanced functionality to navigate through the map and retrieve keys and values that are "near" a given entry. Implementing classes like TreeMap
implement NavigableMap
, making it the most commonly used map when key-ordering and navigation are required.
In this article, we will discuss the NavigableMap
interface, its key methods, and provide practical examples of how it can be used in your Java projects.
The NavigableMap
interface is part of the java.util
package and extends SortedMap
to provide additional methods for navigating through the sorted map. It allows you to retrieve the closest matches for a given key, find entries greater than or less than a certain key, and perform navigational operations in a map that is already sorted.
Key features of NavigableMap
:
NavigableMap
allow you to specify whether the navigation should include the given key or exclude it.subMap()
, headMap()
, and tailMap()
which allow you to create views of specific portions of the map.The NavigableMap
interface provides several methods that enhance navigation and sorting. Here are some of the most important ones:
This method returns the first key that is strictly greater than the specified key, or null
if no such key exists.
K higherKey(K key);
This method returns the last key that is strictly less than the specified key, or null
if no such key exists.
K lowerKey(K key);
This method returns the least key that is greater than or equal to the specified key, or null
if no such key exists.
K ceilingKey(K key);
This method returns the greatest key that is less than or equal to the specified key, or null
if no such key exists.
K floorKey(K key);
This method retrieves and removes the first (lowest) entry in the map, or returns null
if the map is empty.
Map.Entry<K, V> pollFirstEntry();
This method retrieves and removes the last (highest) entry in the map, or returns null
if the map is empty.
Map.Entry<K, V> pollLastEntry();
This method returns a view of the map with the keys in descending order.
NavigableMap<K, V> descendingMap();
This method returns a view of the portion of the map whose keys are in the specified range. You can specify whether the range should include or exclude the boundary keys.
NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive);
TreeMap
is the most common implementation of NavigableMap
in Java. Below is an example that demonstrates how to use NavigableMap
to navigate and manipulate key-value pairs.
import java.util.*;
public class NavigableMapExample {
public static void main(String[] args) {
// Create a NavigableMap using TreeMap
NavigableMap<String, Integer> map = new TreeMap<>();
// Add some key-value pairs
map.put("Apple", 3);
map.put("Banana", 1);
map.put("Mango", 2);
map.put("Pineapple", 4);
// Print the map
System.out.println("Navigable Map: " + map);
// Demonstrate navigation methods
System.out.println("Higher key than Banana: " + map.higherKey("Banana")); // Output: Mango
System.out.println("Lower key than Mango: " + map.lowerKey("Mango")); // Output: Banana
System.out.println("Ceiling key for 'Grapes': " + map.ceilingKey("Grapes")); // Output: Mango
System.out.println("Floor key for 'Grapes': " + map.floorKey("Grapes")); // Output: Banana
// Polling first and last entries
System.out.println("Poll First Entry: " + map.pollFirstEntry()); // Output: Apple=3
System.out.println("Poll Last Entry: " + map.pollLastEntry()); // Output: Pineapple=4
// Print the map after polling
System.out.println("Navigable Map after polling: " + map);
// Get a descending map
NavigableMap<String, Integer> descendingMap = map.descendingMap();
System.out.println("Descending Map: " + descendingMap);
// Submap example
NavigableMap<String, Integer> subMap = map.subMap("Banana", true, "Mango", true);
System.out.println("SubMap (Banana to Mango): " + subMap);
}
}
Output:
Navigable Map: {Apple=3, Banana=1, Mango=2, Pineapple=4}
Higher key than Banana: Mango
Lower key than Mango: Banana
Ceiling key for 'Grapes': Mango
Floor key for 'Grapes': Banana
Poll First Entry: Apple=3
Poll Last Entry: Pineapple=4
Navigable Map after polling: {Banana=1, Mango=2}
Descending Map: {Mango=2, Banana=1}
SubMap (Banana to Mango): {Banana=1, Mango=2}
Navigation Methods:
higherKey("Banana")
returns "Mango"
, which is the next key after "Banana"
.lowerKey("Mango")
returns "Banana"
, which is the key before "Mango"
.ceilingKey("Grapes")
returns "Mango"
because it is the closest key greater than or equal to "Grapes"
.floorKey("Grapes")
returns "Banana"
because it is the closest key less than or equal to "Grapes"
.Polling:
pollFirstEntry()
removes and returns the first entry ("Apple=3"
).pollLastEntry()
removes and returns the last entry ("Pineapple=4"
).Descending Map: The descendingMap()
method returns a map with the entries in reverse order.
SubMap: The subMap("Banana", true, "Mango", true)
method returns a sub-map from "Banana"
to "Mango"
, including both "Banana"
and "Mango"
.
You should use NavigableMap
when:
NavigableMap
provides efficient methods for these tasks.