【Java】レッスン4-2: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:クラス

<<前のページ

学習記事一覧

次のページ>>

Setコレクション入門|HashSetとTreeSetの特徴と使い方

Javaで重複を許さないデータの集まりを扱う場合に便利なのがSetインターフェースです。

特に代表的な実装クラスであるHashSetTreeSetは、どちらも要素の重複を防ぎますが、データの格納順や並び替えの有無などに違いがあります。

本記事では、それぞれの特徴や使い方、適した利用シーンを初心者にもわかりやすく解説します。

これを学べば、目的に応じて適切なSetクラスを選び、効率的かつ安全にデータを管理できるようになるでしょう。

それでは、HashSetとTreeSetの違いと活用法を見ていきましょう。

HashSetとは何か?|宣言方法とコード例

HashSet はSetインターフェースの実装クラスの一つで、順序を保持しないコレクションです。

要素が重複しないように管理され、格納された順序が保証されません。これは内部的にハッシュテーブルを使用して要素を管理するためです。

HashSetを使用するには、Scannerなどと同様にインポートした上でインスタンス化する必要があります。

import java.util.HashSet;	// ArrayListクラスのインポート

HashSet<型> 変数 = new HashSet<>();	// HashSetクラスのインスタンスを作成

実際にHashSetを作成する例を見てみましょう。

またHashSetはArrayListと同様にadd,contain,removeメソッドが使用できますので、それらを使った操作も同時に見ていきます。

import java.util.HashSet;	// HashSetを使用するためのインポート文

public class HashSetExample {
    public static void main(String[] args) {	// メインメソッド

        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]

TreeSetとは何か?|順序付きSetの宣言方法とコード例

TreeSet はSetインターフェースを実装したクラスで、要素を昇順に自動的に並び替えて保持する特性を持っています。

内部的には赤黒木というデータ構造を使用し、要素の追加や削除が行われるたびに要素をソートします。

TreeSetも、使用するにまインポートした上でインスタンス化する必要があります。

import java.util.TreeSet;	// TreeSetクラスのインポート

TreeSet<型> 変数 = new TreeSet<>();	// TreeSetクラスのインスタンスを作成

以下のコードは、TreeSetを使った基本的な操作の例です。

import java.util.TreeSet;	// TTreeSetを使用するためのインポート文

public class TreeSetExample {
    public static void main(String[] args) {	// メインメソッド

      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]

HashSetとTreeSetの違い|機能・速度・null対応の比較表

特徴HashSetTreeSet
順序順序を保持しない昇順にソートされる
処理速度検索・追加が高速ソートがあるため少し遅い
null要素許可される許可されない
データ構造ハッシュテーブル赤黒木
  • HashSet:順序が不要で、パフォーマンス重視の場合に適する
  • TreeSet:順序を保ちながらデータを管理したい場合適する

どちらも一長一短があるため、目的に応じて使い分けることが大切です。

まずはこの2つのコレクションを実際にコードで試し、理解を深めてください。

まとめ|用途に応じたSetコレクション選択の基礎

今回の学習では、HashSetTreeSetそれぞれの特徴や宣言方法、使用例、そして機能や速度、null対応の違いについて学びました。

これにより、データの重複を防ぎながら、用途に応じて最適なSetコレクションを選択し、効率的かつ安全にデータを管理できるようになります。

コレクションの選択はプログラムの性能や可読性にも直結する重要なスキルです。

ここで得た知識を土台に、さらに幅広いデータ構造の活用に挑戦していきましょう。

練習問題|HashSetとTreeSetの動作を比較して理解しよう

Javaのコレクションフレームワークを理解するために、HashSetとTreeSetを使って生徒の名前を管理するプログラムを作成しましょう。

このプログラムではユーザーから3人の生徒の名前を入力し、それらをHashSetとTreeSetに格納して表示します。

HashSetは名前を追加した順に表示し、TreeSetは名前をアルファベット順に表示します。

この問題の要件

以下の要件に従ってコードを完成させてください。

  • ユーザーから3人の生徒の名前を入力し、それらの名前をHashSetに格納すること。
  • HashSetの内容を表示すること。
  • HashSetの内容をTreeSetに格納し、名前をアルファベット順に表示すること。
  • printSetというメソッドを作成し、セットの内容を表示すること。

ただし、以下のような実行結果となること。

生徒の名前を入力してください: 田中
生徒の名前を入力してください: 鈴木
生徒の名前を入力してください: 佐藤
HashSetを使って記載:
田中
鈴木
佐藤
TreeSetを使って名前のアルファベット順に記載:
佐藤
鈴木
田中

この問題を解くヒント

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

Q
ヒント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内の各名前を出力

Q
ヒント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);
        }
    }
}

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。

練習問題の解答と解説

この問題の正解コードとその解説は以下の通りです。

クリックして開いて確認してください。

Q
正解コード
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);
        }
    }
}
Q
正解コードの解説

コードをブロックごとに分割して解説します。

スキャナを使ってユーザーから入力を受け取る

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に追加しています。

HashSetaddメソッドは要素をコレクションに追加するために使いますが、すでに同じ名前が入っている場合は追加されません。

TreeSetを作成して名前をソートする

TreeSet<String> studentTreeSet = new TreeSet<>(studentHashSet);

次にHashSetから名前を取り出して、それをアルファベット順にソートするためにTreeSetを作成します。

TreeSetは要素を常に昇順に保ちながら管理するデータ構造です。

この行ではHashSetTreeSetのコンストラクタに渡して、名前を自動的にソートしています。

HashSetとTreeSetの内容を表示する

printSet(studentHashSet);
printSet(studentTreeSet);

最後にprintSetメソッドを使って、HashSetTreeSetの内容をそれぞれ表示しています。

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でも同じように使えます。

もっと分かりやすい学習サイトにするために

この記事を読んで「ここが分かりにくかった」「ここが難しかった」等の意見を募集しています。

世界一わかりやすいJava学習サイトにするため、ぜひ 問い合わせフォーム からご意見下さい。

<<前のページ

学習記事一覧

次のページ>>

記事URLをコピーしました