Java入門 #18 - HashSet(重複しない集合)

入門 | 10分 で読める | 2026.05.02

公式ドキュメント

この記事の要点

HashSet は重複を許さない集合(Set)を実現するクラス
• `add()` で追加、`contains()` で存在確認、`remove()` で削除
• 配列やリストから HashSet を作ることで重複削除ができる

Set とは

Set(セット、集合)は「重複を許さない要素の集まり」です。数学の「集合」と同じ概念です。

用語説明
Setインターフェース(契約)。重複不可のコレクション
HashSetSet を実装した代表的なクラス。順序なし
LinkedHashSet挿入順を保持する Set
TreeSet自動的にソートされる Set(要素が Comparable)

ポイント: 同じ要素を複数回 `add()` しても、実際には1つしか保存されません。これが Set の最大の特徴です。

List と Set の違い

項目List(例: ArrayList)Set(例: HashSet)
重複許可(同じ値を複数持てる)不可(自動排除)
順序あり(インデックス順)なし(HashSet の場合)
アクセスget(index) で取得可インデックスアクセス不可
主な用途学生リスト、タスクリストユニーク要素の管理、重複削除

HashSet の基本的な使い方

1. import

import java.util.HashSet;
import java.util.Set;

2. HashSet の宣言と生成

// Java 21
Set<String> uniqueNames = new HashSet<>();

3. 要素を追加する(add)

uniqueNames.add("Alice");
uniqueNames.add("Bob");
uniqueNames.add("Alice");  // 重複。実際には追加されない

System.out.println(uniqueNames.size());  // 2(Alice は1つだけ)

add() の戻り値は boolean で、追加に成功したら true、既に存在していたら false です。

boolean added1 = uniqueNames.add("Charlie");  // true
boolean added2 = uniqueNames.add("Charlie");  // false(既に存在)

4. 要素が存在するか確認(contains)

if (uniqueNames.contains("Alice")) {
    System.out.println("Alice は登録済み");
}

5. 要素を削除する(remove)

uniqueNames.remove("Bob");  // Bob を削除

6. 要素数を確認(size)

int count = uniqueNames.size();

7. 全削除(clear)

uniqueNames.clear();

HashSet の主要メソッド

メソッド説明戻り値
add(E element)要素を追加(重複なら追加しない)boolean(追加成功なら true)
contains(Object o)要素が存在するかboolean
remove(Object o)要素を削除boolean(削除成功なら true)
size()要素数int
isEmpty()空かどうかboolean
clear()全削除void

注意: HashSet は**順序を保証しません**。for 文で走査する際、追加順と異なる順序で出てくることがあります。

実践例: 重複削除

配列やリストから重複を取り除きたい場合、HashSet に変換するのが定石です。

// Java 21
import java.util.HashSet;
import java.util.Set;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        String[] fruits = {"Apple", "Banana", "Apple", "Orange", "Banana", "Apple"};

        // 配列 → HashSet で重複削除
        Set<String> uniqueFruits = new HashSet<>(Arrays.asList(fruits));

        System.out.println("ユニークな果物:");
        for (String fruit : uniqueFruits) {
            System.out.println(fruit);
        }

        System.out.println("\n元の配列の長さ: " + fruits.length);  // 6
        System.out.println("重複削除後: " + uniqueFruits.size());  // 3
    }
}

出力(順序は不定):

ユニークな果物:
Apple
Banana
Orange

元の配列の長さ: 6
重複削除後: 3

ポイント: `new HashSet<>(Arrays.asList(配列))` で、配列を Set に変換できます。これだけで重複が自動排除されます。

List vs Set(使い分けの例)

状況推奨理由
学生の出席リストList同じ人が複数回記録される場合あり
ログインユーザーID(オンライン中)Set重複を許さない
購買履歴(時系列)List順序と重複が重要
タグ(ブログ記事など)Set同じタグを2回登録しない
アクセスしたページURL(履歴)List順序が大事
訪問済みURL(重複チェック)Set訪問済みかどうかだけ知りたい

拡張 for 文で走査

HashSet は順序がありませんが、全要素を走査できます。

// Java 21
import java.util.HashSet;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
        Set<Integer> numbers = new HashSet<>();
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        numbers.add(20);  // 重複、追加されない

        System.out.println("Set の要素:");
        for (int num : numbers) {
            System.out.println(num);
        }
    }
}

出力(順序は不定):

Set の要素:
10
20
30

不変セット(Set.of)

不変セットは、一度作ったら変更不可です。Java 9 以降、Set.of() で作成できます。

// Java 21
import java.util.Set;

Set<String> colors = Set.of("Red", "Green", "Blue");

System.out.println(colors.contains("Red"));  // true
System.out.println(colors.size());  // 3

// 変更しようとするとエラー
// colors.add("Yellow");  // UnsupportedOperationException
特徴説明
不変add / remove が使えない
簡潔要素を並べるだけ
重複禁止Set.of("A", "A")IllegalArgumentException
null 禁止Set.of(null)NullPointerException

注意: `Set.of()` は重複を許しません。重複があると実行時エラーになります。

実践例: ユニーク要素の抽出

ユーザー入力から重複を排除して一覧を作成します。

// Java 21
import java.util.HashSet;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
        String input = "apple,banana,apple,orange,banana,grape,apple";
        String[] items = input.split(",");

        Set<String> uniqueItems = new HashSet<>();
        for (String item : items) {
            if (uniqueItems.add(item)) {
                System.out.println("新規追加: " + item);
            } else {
                System.out.println("重複検出: " + item);
            }
        }

        System.out.println("\nユニーク項目:");
        uniqueItems.forEach(System.out::println);
    }
}

出力:

新規追加: apple
新規追加: banana
重複検出: apple
新規追加: orange
重複検出: banana
新規追加: grape
重複検出: apple

ユニーク項目:
apple
banana
orange
grape

補足: `add()` の戻り値(boolean)を活用すると、追加と重複検出を同時に行えます。

HashSet の内部動作(補足)

HashSet は内部で HashMap を使っています。要素を「キー」として格納し、値はダミーオブジェクトです。

操作計算量(平均)備考
add(E)O(1)ハッシュ衝突が少ない場合
contains(E)O(1)同上
remove(E)O(1)同上

ポイント: HashSet は検索(contains)が超高速(O(1))です。ArrayList の `contains()` は O(n) なので、大量の要素から「存在チェック」を繰り返すなら HashSet が圧倒的に速いです。

List / Set / Map の総まとめ

これまで学んだ3大コレクションの比較です。

種類代表クラス重複順序主なメソッド用途
ListArrayListありadd / get / set / remove学生リスト、履歴
SetHashSet不可なしadd / contains / removeタグ、ユニークID
MapHashMapキー不可、値可なしput / get / containsKey辞書、設定、カウント

ポイント: 「重複を許すか」「順序が必要か」「名前で引くか」で使い分けます。迷ったら、重複NGならSet、名前引きならMap、それ以外はListです。

まとめ

概念説明
Set重複を許さないコレクションのインターフェース
HashSetハッシュテーブルベースの実装。高速(O(1))
add / contains / remove基本操作。add は重複時に false を返す
重複削除配列やリストから HashSet を作成するだけで実現
順序HashSet は順序なし。LinkedHashSet で挿入順を保持
Set.of()不変セットを簡潔に作成(Java 9以降)

次のステップ(発展学習へ)

おめでとうございます! Java入門シリーズのコレクション編(List / Map / Set)が完了しました。これで基本的なデータ構造の選択ができるようになりました。

さらに学ぶべきこと

分野学習内容理由
例外処理try-catch-finally, throwsエラーハンドリングの基本
ファイル入出力Files, BufferedReader, Pathデータの永続化
継承とインターフェースextends, implements, 抽象クラスオブジェクト指向設計
ラムダ式とStream APIstream(), filter(), map()関数型プログラミング
ジェネリクス応用独自ジェネリッククラスの作成型安全な設計

本サイトに今後、例外処理やファイル入出力の入門記事が追加される予定です。

補足: コレクションを使いこなせるようになったら、Stream API(Java 8以降)を学ぶと、データ処理が劇的に簡潔になります。`list.stream().filter(...).map(...).collect(...)` のような記法です。

参考リソース

この技術を体系的に学びたいですか?

未来学では東証プライム上場企業のITエンジニアが24時間サポート。月額24,800円から、退会金0円のオンラインIT塾です。

メールで無料相談する
← 一覧に戻る