【Java】レッスン4-02:HashSetとTreeSetの使い分け方を学ぼう

一つ前のページではArrayListについて学習しました。
今回は HashSetとTreeSet について見ていきましょう。
Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:メソッド編
Lesson4:コレクション編
・Lesson4-1:ArrayListを理解しよう
・Lesson4-2:HashSetとTreeSetを理解しよう ◁今回はココ
・Lesson4-3:HashMapを理解しよう
・Lesson4-4:TreeMapを理解しよう
・確認問題4-☆1:ナインゲームを作ろう
・確認問題4-☆2:アラビア数字をローマ数字に変換するアプリを作ろう
Lesson5:クラス編
JavaのSetコレクション入門|HashSetとTreeSetの違いとは

Javaのコレクションフレームワークは、データを効率的に管理し操作するために非常に役立ちます。
その中でも「Set」インターフェースは、重複する要素を許さないコレクションです。
今回はHashSet
とTreeSet
という2つの代表的な実装クラスについて解説します。
HashSetの特徴と使用シーンを解説
HashSet
はSetインターフェースの実装クラスの一つで、順序を保持しないコレクションです。
要素が重複しないように管理され、格納された順序が保証されません。これは内部的にハッシュテーブルを使用して要素を管理するためです。
特徴:
- 要素の重複を許さない。
- 順序は保証されない。
null
要素も一つだけ追加可能。- 検索や削除が高速。
HashSet
の基本的な使い方
以下のコードは、HashSet
を使って基本的な操作を行う例です。
import java.util.HashSet; // HashSetを使用するためのインポート文 public class HashSetExample { public static void main(String[] args) { // HashSetの作成 HashSet<String> set = new HashSet<>();//String型のsetというHashSetを作成 // addメソッドを使って要素の追加 set.add("Apple"); set.add("Banana"); set.add("Orange"); set.add("Apple"); // 重複要素(追加されません) // HashSetの内容を表示 System.out.println("HashSetの内容: " + set); // containsメソッドを使って要素の検索 if (set.contains("Banana")) { System.out.println("Bananaが含まれています"); } // removeメソッドを使って要素の削除 set.remove("Orange"); System.out.println("削除後のHashSet: " + set); } }
このコードを実行すると以下のように出力されます。
HashSetの内容: [Banana, Apple, Orange] Bananaが含まれています 削除後のHashSet: [Banana, Apple]
HashSet
の使いどころ
- データの順序が重要ではない場合。
- 高速な検索や削除が求められる場合。
TreeSetの基本とソート機能の活用法
TreeSet
はSetインターフェースを実装したクラスで、要素を昇順に自動的に並び替えて保持する特性を持っています。
内部的には赤黒木というデータ構造を使用し、要素の追加や削除が行われるたびに要素をソートします。
特徴:
- 自動的に要素を昇順にソート。
- 要素の重複を許さない。
null
要素を保持できない(HashSet
とは異なる点)。
TreeSet
の基本的な使い方
以下のコードは、TreeSet
を使った基本的な操作の例です。
import java.util.TreeSet; // TTreeSetを使用するためのインポート文 public class TreeSetExample { public static void main(String[] args) { // TreeSetの作成 TreeSet<String> set = new TreeSet<>(); //String型のsetというTreeSetを作成 // addメソッドを使って要素の追加(自動的にソートされます) set.add("Banana"); set.add("Apple"); set.add("Orange"); set.add("Grape"); // TreeSetの内容を表示(昇順に並び替えられる) System.out.println("TreeSetの内容: " + set); // 最初の要素を取得 System.out.println("最初の要素: " + set.first()); // 最後の要素を取得 System.out.println("最後の要素: " + set.last()); // removeメソッドを使って要素の削除 set.remove("Banana"); System.out.println("削除後のTreeSet: " + set); } }
このコードを実行すると以下のように出力されます。
TreeSetの内容: [Apple, Banana, Grape, Orange] 最初の要素: Apple 最後の要素: Orange 削除後のTreeSet: [Apple, Grape, Orange]
TreeSet
の使いどころ
- データを常にソートされた状態で保持したい場合。
- 特定の範囲での検索やソートが必要な場合。
機能・速度・null対応の違いを比較しよう
特徴 | HashSet | TreeSet |
順序 | 順序を保持しない | 昇順にソートされる |
処理速度 | 検索・追加が高速 | ソートがあるため少し遅い |
null要素 | 許可される | 許可されない |
データ構造 | ハッシュテーブル | 赤黒木 |
使用目的に応じたSetクラスの選び方
- 順序が不要で、パフォーマンス重視の場合:
HashSet
- 順序を保ちながらデータを管理したい場合:
TreeSet
どちらも一長一短があるため、目的に応じて使い分けることが大切です。
まずはこの2つのコレクションを実際にコードで試し、理解を深めてください。
練習問題|HashSetとTreeSetの動作を比較して理解しよう

Javaのコレクションフレームワークを理解するために、HashSetとTreeSetを使って生徒の名前を管理するプログラムを作成しましょう。
このプログラムではユーザーから3人の生徒の名前を入力し、それらをHashSetとTreeSetに格納して表示します。
HashSetは名前を追加した順に表示し、TreeSetは名前をアルファベット順に表示します。
この問題の要件
以下の要件に従ってコードを完成させてください。
- ユーザーから3人の生徒の名前を入力し、それらの名前をHashSetに格納すること。
- HashSetの内容を表示すること。
- HashSetの内容をTreeSetに格納し、名前をアルファベット順に表示すること。
printSet
というメソッドを作成し、セットの内容を表示すること。
ただし、以下のような実行結果となること。
生徒の名前を入力してください: 田中 生徒の名前を入力してください: 鈴木 生徒の名前を入力してください: 佐藤 HashSetを使って記載: 田中 鈴木 佐藤 TreeSetを使って名前のアルファベット順に記載: 佐藤 鈴木 田中
この問題を解くヒント
1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。
- ヒント1【コードの構成を見る】
-
正解のコードは上から順に以下のような構成となっています。
1:HashSetクラスをインポート
2:Scannerクラスをインポート
3:TreeSetクラスをインポート
4:SetExampleクラスの定義
□ mainメソッドの定義
□ □ Scannerオブジェクトscannerの初期化
□ □ HashSetオブジェクトstudentHashSetの初期化
□ □ forループを3回繰り返すように設定
□ □ □ 「生徒の名前を入力してください: 」と出力
□ □ □ ユーザーの入力を文字列として読み取り、変数nameに代入
□ □ □ studentHashSetにnameを追加
□ □ TreeSetオブジェクトstudentTreeSetをstudentHashSetで初期化
□ □ 「HashSetを使って記載:」と出力
□ □ printSetメソッドでstudentHashSetの内容を出力
□ □ 「TreeSetを使って名前のアルファベット順に記載:」と出力
□ □ printSetメソッドでstudentTreeSetの内容を出力
□ printSetメソッドの定義
□ □ forループでSet内の各名前を出力
- ヒント2【穴埋め問題にする】
-
以下のコードをコピーし、コメントに従ってコードを完成させて下さい。
import java.util.HashSet; import java.util.Scanner; import java.util.TreeSet; public class SetExample { // メインメソッド public static void main(String[] args) { // スキャナを作成してユーザー入力を受け取る Scanner scanner = new Scanner(System.in); /*【穴埋め問題1】 ここでHashSetを作成し、String型の要素を格納できるようにしてください。 */ // 3人の生徒の名前を入力してもらう for (int i = 0; i < 3; i++) { System.out.print("生徒の名前を入力してください: "); String name = scanner.nextLine(); /*【穴埋め問題2】 ここでHashSetにユーザーが入力した名前を追加してください。 */ } /*【穴埋め問題3】 ここでTreeSetを作成し、HashSetを使って初期化してください。 */ // HashSetの内容を表示 System.out.println("HashSetを使って記載:"); printSet(studentHashSet); // TreeSetの内容を表示 System.out.println("TreeSetを使って名前のアルファベット順に記載:"); printSet(studentTreeSet); } // Setの内容を表示するメソッド public static void printSet(java.util.Set<String> set) { // Setから名前を一つずつ取り出して表示 for (String name : set) { System.out.println(name); } } }
このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。
練習問題の解答と解説
この問題の正解コードとその解説は以下の通りです。
クリックして開いて確認してください。
- 正解コード
-
import java.util.HashSet; import java.util.Scanner; import java.util.TreeSet; public class SetExample { // メインメソッド public static void main(String[] args) { // スキャナを作成してユーザー入力を受け取る Scanner scanner = new Scanner(System.in); // 生徒の名前を格納するHashSetを作成 HashSet<String> studentHashSet = new HashSet<>(); // 3人の生徒の名前を入力してもらう for (int i = 0; i < 3; i++) { System.out.print("生徒の名前を入力してください: "); String name = scanner.nextLine(); studentHashSet.add(name); } // 生徒の名前を格納するTreeSetを作成 TreeSet<String> studentTreeSet = new TreeSet<>(studentHashSet); // HashSetの内容を表示 System.out.println("HashSetを使って記載:"); printSet(studentHashSet); // TreeSetの内容を表示 System.out.println("TreeSetを使って名前のアルファベット順に記載:"); printSet(studentTreeSet); } // Setの内容を表示するメソッド public static void printSet(java.util.Set<String> set) { // Setから名前を一つずつ取り出して表示 for (String name : set) { System.out.println(name); } } }
- 正解コードの解説
-
コードをブロックごとに分割して解説します。
スキャナを使ってユーザーから入力を受け取る
Scanner scanner = new Scanner(System.in);
Scanner
クラスを使ってユーザーからコンソールで入力を受け取る準備をしています。System.in
はコンソール(キーボード入力)からの入力を表します。HashSetを作成する
HashSet<String> studentHashSet = new HashSet<>();
ここでは生徒の名前を格納するための
HashSet
を作成しています。HashSet
は、要素を重複させずに管理するデータ構造です。順序は保証されませんが、要素の追加や削除が高速で行われます。
生徒の名前を入力してHashSetに追加する
for (int i = 0; i < 3; i++) { System.out.print("生徒の名前を入力してください: "); String name = scanner.nextLine(); studentHashSet.add(name); }
for
ループを使って3人分の生徒の名前をユーザーから入力してもらい、それをHashSet
に追加しています。HashSet
のadd
メソッドは要素をコレクションに追加するために使いますが、すでに同じ名前が入っている場合は追加されません。TreeSetを作成して名前をソートする
TreeSet<String> studentTreeSet = new TreeSet<>(studentHashSet);
次に
HashSet
から名前を取り出して、それをアルファベット順にソートするためにTreeSet
を作成します。TreeSet
は要素を常に昇順に保ちながら管理するデータ構造です。この行では
HashSet
をTreeSet
のコンストラクタに渡して、名前を自動的にソートしています。HashSetとTreeSetの内容を表示する
printSet(studentHashSet); printSet(studentTreeSet);
最後に
printSet
メソッドを使って、HashSet
とTreeSet
の内容をそれぞれ表示しています。HashSet
は追加された順序が保証されないため、表示順は入力された順とは異なる可能性がありますが、TreeSet
はアルファベット順で表示されます。Setの内容を表示するためのメソッド
public static void printSet(java.util.Set<String> set) { for (String name : set) { System.out.println(name); } }
Set
に格納されている名前を1つずつ取り出し、for-each
ループでコンソールに表示しています。このメソッドは
HashSet
でもTreeSet
でも同じように使えます。