NavigableMap / NavigableSet(近傍検索) — 前後関係の取得
NavigableMap と NavigableSet は、ソート済みのデータ構造に「近傍検索(前後関係の取得)」を追加したインターフェースです。
初心者が理解すべきポイントは「ソート順を保ちながら、指定したキーや要素の前後を簡単に探せる」ということです。
特徴
- NavigableMap: ソート済みの
Map。代表的な実装はTreeMap。 - NavigableSet: ソート済みの
Set。代表的な実装はTreeSet。 - 近傍検索メソッド:
lower,floor,ceiling,higherなどで「指定値の前後」を取得できる。 - 範囲ビュー:
subMap,headMap,tailMapで部分範囲を切り出せる。
👉 「順序付きデータ」+「近傍検索」が必要な場面に最適。
基本コード例(NavigableMap)
import java.util.*;
public class NavigableMapDemo {
public static void main(String[] args) {
NavigableMap<Integer, String> map = new TreeMap<>();
map.put(10, "Ten");
map.put(20, "Twenty");
map.put(30, "Thirty");
map.put(40, "Forty");
System.out.println(map.floorEntry(25)); // 20=Twenty(25以下の最大キー)
System.out.println(map.ceilingEntry(25)); // 30=Thirty(25以上の最小キー)
System.out.println(map.lowerEntry(20)); // 10=Ten(20より小さい最大キー)
System.out.println(map.higherEntry(20)); // 30=Thirty(20より大きい最小キー)
}
}
Java基本コード例(NavigableSet)
import java.util.*;
public class NavigableSetDemo {
public static void main(String[] args) {
NavigableSet<Integer> set = new TreeSet<>();
set.addAll(List.of(10, 20, 30, 40));
System.out.println(set.floor(25)); // 20(25以下の最大要素)
System.out.println(set.ceiling(25)); // 30(25以上の最小要素)
System.out.println(set.lower(20)); // 10(20より小さい最大要素)
System.out.println(set.higher(20)); // 30(20より大きい最小要素)
}
}
Java近傍検索メソッドまとめ
| メソッド | 意味(Mapの場合は Entry、Setの場合は要素) |
|---|---|
lower(x) | x より 小さい最大 |
floor(x) | x 以下の最大 |
ceiling(x) | x 以上の最小 |
higher(x) | x より 大きい最小 |
👉 「より小さい」「以下」「以上」「より大きい」を区別して覚える。
例題で練習
例題1: 成績管理(点数の近傍検索)
NavigableMap<Integer, String> scores = new TreeMap<>();
scores.put(60, "Tanaka");
scores.put(70, "Sato");
scores.put(80, "Suzuki");
scores.put(90, "Kato");
System.out.println(scores.floorEntry(75)); // 70=Sato(75以下の最大)
System.out.println(scores.ceilingEntry(75)); // 80=Suzuki(75以上の最小)
Java例題2: 日付ごとのイベント管理
NavigableMap<String, String> events = new TreeMap<>();
events.put("2025-12-01", "Meeting");
events.put("2025-12-05", "Workshop");
events.put("2025-12-10", "Conference");
System.out.println(events.lowerEntry("2025-12-07")); // 2025-12-05=Workshop
System.out.println(events.higherEntry("2025-12-07")); // 2025-12-10=Conference
Java例題3: NavigableSet で範囲検索
NavigableSet<Integer> nums = new TreeSet<>(List.of(10, 20, 30, 40, 50));
System.out.println(nums.subSet(20, true, 40, true)); // [20, 30, 40]
System.out.println(nums.headSet(30, false)); // [10, 20]
System.out.println(nums.tailSet(30, true)); // [30, 40, 50]
Javaテンプレート集
NavigableMap の宣言
NavigableMap<KeyType, ValueType> map = new TreeMap<>();
JavaNavigableSet の宣言
NavigableSet<Type> set = new TreeSet<>();
Java近傍検索
map.floorEntry(key);
map.ceilingEntry(key);
map.lowerEntry(key);
map.higherEntry(key);
set.floor(value);
set.ceiling(value);
set.lower(value);
set.higher(value);
Java範囲ビュー
map.subMap(fromKey, true, toKey, false);
set.subSet(fromVal, true, toVal, true);
Java実務でのコツ
- 範囲検索: 日付や数値の範囲検索に便利。
- 近傍検索: 「直前」「直後」のデータを効率的に取得できる。
- 順序付きデータ: TreeMap/TreeSet は常にソート済みなので、ランキングや時系列管理に最適。
- スレッド安全: TreeMap/TreeSet は非同期。並行環境では
ConcurrentSkipListMap/ConcurrentSkipListSetを検討。
まとめ
- NavigableMap / NavigableSet は「ソート+近傍検索」ができるコレクション。
- lower/floor/ceiling/higher を使えば前後関係を簡単に取得可能。
- 範囲ビューで部分集合を扱える。
👉 練習課題として「TreeMap に日付をキーとしてイベントを登録し、指定日付の直前・直後のイベントを検索する」プログラムを書いてみると、NavigableMap の便利さが体感できます。
