0Pricing
Java Academy · レッスン

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 Charlie

NavigableSet のメソッド: 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 1

Comparator によるカスタム順序

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 = 4

TreeSet と 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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. TreeMap:ソートされたキーと値のペア
  2. サブマップと範囲ビュー
  3. TreeSet と NavigableSet
  4. Tree コレクションのカスタム順序
← Java Academyに戻る