Submaps and Range Views
Extract subMap, headMap, and tailMap views for range-based lookups in sorted maps.
Submaps and Range Views is a free Java Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Java Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Range Views in TreeMap
TreeMap's subMap, headMap, and tailMap return backed views — they reflect changes in the underlying map and vice versa. Changes through the view are reflected in the original.
TreeMap<Integer, String> map = new TreeMap<>();
for (int i = 1; i <= 10; i++) map.put(i * 10, "item" + i);
var view = map.subMap(30, 70); // [30, 70)
System.out.println(view); // {30=item3, 40=item4, 50=item5, 60=item6}
map.put(45, "new"); // also visible through view!
System.out.println(view.containsKey(45)); // trueheadMap: Keys Below a Bound
headMap(toKey) returns all entries with keys strictly less than toKey. Use the inclusive variant headMap(toKey, true) to include the bound.
TreeMap<String, Integer> words = new TreeMap<>();
"banana cherry apple date elderberry".chars()
.mapToObj(c -> String.valueOf((char)c)).distinct()
.forEach(w -> words.put(w, w.length()));
// Actually let's use real words:
TreeMap<String, Integer> wc = new TreeMap<>();
wc.put("apple",5); wc.put("banana",6); wc.put("cherry",6); wc.put("date",4);
System.out.println(wc.headMap("cherry")); // {apple=5, banana=6}tailMap: Keys From a Bound
tailMap(fromKey) returns all entries with keys ≥ fromKey.
TreeMap<Integer, String> grades = new TreeMap<>();
grades.put(50,"F"); grades.put(60,"D"); grades.put(70,"C"); grades.put(80,"B"); grades.put(90,"A");
// All passing grades (>= 60)
var passing = grades.tailMap(60);
System.out.println(passing); // {60=D, 70=C, 80=B, 90=A}subMap with Inclusive Bounds
The 4-argument subMap(from, fromInclusive, to, toInclusive) gives full control over boundary inclusivity:
TreeMap<Integer, String> map = new TreeMap<>();
for (int i = 10; i <= 100; i += 10) map.put(i, "v"+i);
// [30, 60] — both inclusive
System.out.println(map.subMap(30, true, 60, true));
// {30=v30, 40=v40, 50=v50, 60=v60}
// (30, 60) — both exclusive
System.out.println(map.subMap(30, false, 60, false));
// {40=v40, 50=v50}Modifying Through a View
Put/remove operations on a subMap view are reflected in the original map (and vice versa). Attempting to insert a key outside the view's range throws an exception.
TreeMap<Integer, String> map = new TreeMap<>();
for (int i = 1; i <= 5; i++) map.put(i * 10, "v" + i);
var view = map.subMap(20, 40); // [20, 40)
view.remove(20); // removes from both view and original map
System.out.println(map.containsKey(20)); // false
// This would throw IllegalArgumentException:
// view.put(50, "out of range");Use Case: Log Range Query
Retrieve all log entries between two timestamps using a TreeMap range view:
import java.time.*;
TreeMap<LocalDateTime, String> logs = new TreeMap<>();
logs.put(LocalDateTime.of(2024,1,1,8,0), "Server start");
logs.put(LocalDateTime.of(2024,1,1,10,0), "Request spike");
logs.put(LocalDateTime.of(2024,1,1,14,0), "Maintenance");
logs.put(LocalDateTime.of(2024,1,1,18,0), "Server stop");
var morning = logs.subMap(
LocalDateTime.of(2024,1,1,8,0), true,
LocalDateTime.of(2024,1,1,12,0), false
);
morning.forEach((t,m) -> System.out.println(t+" : "+m));Use Case: Price Range Lookup
Find all products in a price range using TreeMap keys as prices:
TreeMap<Double, String> products = new TreeMap<>();
products.put(9.99, "Pen");
products.put(24.99, "Book");
products.put(49.99, "Headphones");
products.put(299.99, "Tablet");
double min = 10.0, max = 100.0;
var affordable = products.subMap(min, true, max, true);
affordable.forEach((p,n) -> System.out.println(n+" $"+p));
// Book $24.99, Headphones $49.99descending SubMap
Chain descendingMap() on a view for reverse-order navigation:
TreeMap<Integer, String> map = new TreeMap<>();
for (int i = 10; i <= 100; i += 10) map.put(i, "v"+i);
// Get [40, 80] in descending order
map.subMap(40, true, 80, true)
.descendingMap()
.forEach((k,v) -> System.out.println(k + "=" + v));
// 80=v80, 70=v70, 60=v60, 50=v50, 40=v40NavigableMap Interface
NavigableMap extends SortedMap and adds ceiling/floor/higher/lower key navigation plus descending views. TreeMap is the most common implementation; ConcurrentSkipListMap is the thread-safe alternative.
Performance of Views
Submap view operations (get, put, containsKey) are the same O(log n) as the underlying TreeMap. Creating the view itself is O(1) — no copying occurs. Range scans over n keys in the view are O(log N + n) where N is the full map size.
Pitfall: Stale Views
Because views are backed by the original map, a view can become empty or throw if the original map is cleared. Always document that views are live and don't persist them beyond their intended lifecycle.
TreeMap<Integer, String> map = new TreeMap<>();
map.put(10, "a"); map.put(20, "b"); map.put(30, "c");
var view = map.subMap(10, 30);
map.clear(); // view becomes empty
System.out.println(view.size()); // 0 — but no exceptionQuick Check
You call map.subMap(30, false, 70, true) on a TreeMap with keys {10,20,30,40,50,60,70,80}. Which keys are included in the result?
Recap: Submaps and Range Views
Key takeaways:
- subMap, headMap, tailMap return live backed views — no copying
- Changes in view reflect in original map and vice versa
- 4-arg subMap(from, fromInclusive, to, toInclusive) for full boundary control
- Out-of-range puts via a view throw IllegalArgumentException
- Range scan complexity: O(log N + n)
Frequently asked questions
Is the “Submaps and Range Views” lesson free?
Yes — the full text of “Submaps and Range Views” is free to read here on the web, and the Java Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Java Academy course, upgrade to CoddyKit PRO.
What will I learn in “Submaps and Range Views”?
Extract subMap, headMap, and tailMap views for range-based lookups in sorted maps. You practise Java Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Java Academy?
No prior experience is required. Java Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Submaps and Range Views” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Java Academy lesson?
Yes. Every Java Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- TreeMap: Sorted Key-Value Pairs
- Submaps and Range Views
- TreeSet and NavigableSet
- Custom Ordering in Tree Collections