TreeSet と NavigableSet
重複のないソート済み要素を格納し、floor、ceiling、higher、lower で近傍要素を検索します。
「TreeSet と NavigableSet」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。
TreeSet とは
TreeSet は、Red-Black tree を基盤とするソート済みセットです。重複しない要素を、自然順序(または指定したコンパレータ)で昇順に格納します。すべての操作は O(log n) です。
import java.util.TreeSet;
TreeSet<String> names = new TreeSet<>();
names.add("Charlie");
names.add("Alice");
names.add("Bob");
names.add("Alice"); // duplicate ignored
for (String s : names) System.out.print(s + " ");
// Alice Bob CharlieNavigableSet のメソッド: floor、ceiling、lower、higher
TreeSet は NavigableSet を実装し、最も近い要素を見つけるためのナビゲーションメソッドを提供します:
TreeSet<Integer> set = new TreeSet<>();
for (int i = 10; i <= 50; i += 10) set.add(i);
// {10, 20, 30, 40, 50}
System.out.println(set.floor(25)); // 20 (greatest ≤ 25)
System.out.println(set.ceiling(25)); // 30 (smallest ≥ 25)
System.out.println(set.lower(30)); // 20 (strictly less)
System.out.println(set.higher(30)); // 40 (strictly greater)first、last、pollFirst、pollLast
境界要素にアクセスしたり、削除したりします:
TreeSet<String> ts = new TreeSet<>(Set.of("cherry","apple","banana","date"));
System.out.println(ts.first()); // apple
System.out.println(ts.last()); // date
System.out.println(ts.pollFirst()); // apple (removed)
System.out.println(ts.pollLast()); // date (removed)
System.out.println(ts); // [banana, cherry]headSet、tailSet、subSet
ソートされたサブセットのビューを取得します:
TreeSet<Integer> set = new TreeSet<>(Set.of(1,2,3,4,5,6,7,8,9,10));
System.out.println(set.headSet(5)); // [1, 2, 3, 4]
System.out.println(set.tailSet(7)); // [7, 8, 9, 10]
System.out.println(set.subSet(3, 7)); // [3, 4, 5, 6]
// Inclusive upper bound:
System.out.println(set.subSet(3, true, 7, true)); // [3,4,5,6,7]降順の反復処理
逆順にするには descendingIterator() または descendingSet() を使用します:
TreeSet<Integer> ts = new TreeSet<>(Set.of(1,3,5,7,9));
// Descending iterator
var it = ts.descendingIterator();
while (it.hasNext()) System.out.print(it.next() + " ");
// 9 7 5 3 1Comparator によるカスタム順序
Comparator を渡すと、自然順序とは異なる順序でソートできます。たとえば、文字列を長い順に並べられます:
TreeSet<String> byLength = new TreeSet<>(
Comparator.comparingInt(String::length)
.thenComparing(Comparator.naturalOrder())
);
byLength.add("Hi");
byLength.add("Hello");
byLength.add("Hey");
byLength.add("Java");
for (String s : byLength) System.out.print(s + " ");
// Hi Hey Java Helloユースケース: ソートされた一意のユーザー名
ユーザー名を TreeSet に格納すると、自動的に重複が除去され、アルファベット順が維持されます:
TreeSet<String> users = new TreeSet<>();
users.add("alice");
users.add("bob");
users.add("alice"); // ignored
users.add("carol");
System.out.println(users.first()); // alice
System.out.println(users); // [alice, bob, carol]ユースケース: 範囲内の要素数のカウント
subSet を使用して、範囲内の要素数を数えます:
TreeSet<Integer> scores = new TreeSet<>();
for (int s : new int[]{45,62,78,55,90,88,34,71}) scores.add(s);
// Scores between 60 and 89 (inclusive)
int count = scores.subSet(60, true, 89, true).size();
System.out.println("Students in B range: " + count); // 3 (62, 78, 88... wait: 62,78,71,88=4)
// Actually: 62,71,78,88 = 4TreeSet と HashSet と LinkedHashSet の比較
必要な特性に基づいて選択してください:
- HashSet: 操作は O(1)、順序は保証されません
- LinkedHashSet: 操作は O(1)、挿入順になります
- TreeSet: 操作は O(log n)、ソート順になり、ナビゲーションメソッドを利用できます
TreeSet の要素は Comparable を実装するか、Comparator を指定する必要があります。
null 要素
自然順序を使用する場合、TreeSet は null 要素を許可しません。null は比較できないため、NullPointerException がスローされます。null を明示的に処理するカスタムコンパレータを使用すれば、null を格納できます。
TreeSet<String> ts = new TreeSet<>();
try {
ts.add(null); // throws NullPointerException
} catch (NullPointerException e) {
System.out.println("Cannot add null: " + e);
}スレッドセーフティ
TreeSet はスレッドセーフではありません。Collections.synchronizedSortedSet() を使って外部から同期するか、ソートとスレッドセーフの両方に対応した ConcurrentSkipListSet を使用してください。
確認問題
TreeSet<Integer> に {10, 20, 30, 40, 50} が含まれています。set.ceiling(35) は何を返しますか?
まとめ: TreeSet と NavigableSet
要点:
- TreeSet はソートされた一意の要素を格納します(O(log n))
- NavigableSet を実装し、floor、ceiling、lower、higher、first、last を利用できます
- headSet、tailSet、subSet は元のセットに連動する範囲ビューを返します
- 逆順には descendingSet()/descendingIterator() を使用します
- スレッドセーフではないため、並行処理には ConcurrentSkipListSet を使用します
よくある質問
「TreeSet と NavigableSet」レッスンは無料ですか?
はい。「TreeSet と NavigableSet」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。
「TreeSet と NavigableSet」で何を学びますか?
重複のないソート済み要素を格納し、floor、ceiling、higher、lower で近傍要素を検索します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Java Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「TreeSet と NavigableSet」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJava Academyレッスンでコードを書いて実行できますか?
はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- TreeMap:ソートされたキーと値のペア
- サブマップと範囲ビュー
- TreeSet と NavigableSet
- Tree コレクションのカスタム順序