はじめに:Setを知ればJavaがもっと得意になる!
「Javaでリストは使えるけど、Setってなんだろう?」
そんな疑問を持つ方は多いはずです。Set(セット)は、Javaで「重複しないデータの集まり」を表すとても大切なコレクションです。
このブログでは、Java初心者やこれからプログラマーを目指す方に向けて、「Set系コレクションの種類と選び方」をわかりやすく解説します。
転職を目指して学習中の方にも、「業務でどのSetを使えばよいか?」という実践的な判断ポイントが身につきますよ!
1. Setって何?どんなときに使うの?
✔ Setは「重複しない集合」
JavaのSetインターフェースは、要素の重複を許さないデータ構造です。
例えば、同じユーザーIDを2回登録したくないときなどに活躍します。
Set<String> users = new HashSet<>();
users.add("taro");
users.add("hanako");
users.add("taro"); // 無視される
System.out.println(users); // [taro, hanako](順不同)
✔ ListやMapとの違い
| コレクション | 重複OK? | 順序保持 | キーと値のセット |
|---|---|---|---|
| List | OK | 保持 | なし |
| Set | NG | 実装による | なし |
| Map | キーはNG | 保持 | あり(キーと値) |
Setは、「重複を防ぎたいときに使う」のが基本ルールです。
2. Setの種類を知ろう!〜代表的な3つ〜
① HashSet:一番よく使う基本形!
- 特徴:順序なし、重複なし、高速
- 使いどころ:とにかく早くてOK、順番にこだわらないとき
Set<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
set.add("apple"); // 無視
System.out.println(set); // 順序保証なし
- 平均O(1)の高速な操作
- nullの追加OK(1つだけ)
② LinkedHashSet:順序を保ちたいならこれ!
- 特徴:順番あり、重複なし
- 使いどころ:「追加した順序」で要素を保持したいとき
Set<String> set = new LinkedHashSet<>();
set.add("apple");
set.add("banana");
System.out.println(set); // [apple, banana]
- 内部構造は「ハッシュ表+双方向リスト」
- HashSetよりやや重いが、順序が大事な場面で重宝!
③ TreeSet:並び順も大事なら!
- 特徴:自動でソート、重複なし
- 使いどころ:常にソートされた状態を保ちたいとき
Set<String> set = new TreeSet<>();
set.add("banana");
set.add("apple");
System.out.println(set); // [apple, banana]
- 内部構造は「赤黒木」という木構造
- 要素はComparable実装か、Comparatorを渡す必要あり
- nullは入れられない!
3. 迷わないための!Set選びの判断基準チェックリスト
以下の表は、実際の開発現場で「どのSetを使うか」を決めるための判断基準です。
| 判断ポイント | 内容 | おすすめのSet |
|---|---|---|
| 順序を保持したいか? | 追加順をそのまま表示したい | LinkedHashSet |
| 要素を並べて管理したいか? | 自動でソートしてほしい | TreeSet |
| 高速性が最重要か? | とにかく早い追加・検索 | HashSet |
| null を扱いたいか? | null を追加したい | HashSet or LinkedHashSet |
| enum型を使いたいか? | Enum の集合を作りたい | EnumSet |
| スレッド安全性が必要か? | 複数スレッドで安全に使いたい | CopyOnWriteArraySet など |
4. コードで理解するSetの違い【サンプルあり】
HashSetのサンプル
Set<String> set = new HashSet<>();
set.add("one");
set.add("two");
set.add("one"); // 重複無視
System.out.println(set); // [one, two] 順序は不定
LinkedHashSetのサンプル
Set<String> set = new LinkedHashSet<>();
set.add("first");
set.add("second");
System.out.println(set); // [first, second]
TreeSetのサンプル
Set<String> set = new TreeSet<>();
set.add("banana");
set.add("apple");
System.out.println(set); // [apple, banana] 自動ソート
EnumSetのサンプル
enum Day { MON, TUE, WED }
Set<Day> days = EnumSet.of(Day.MON, Day.WED);
System.out.println(days); // [MON, WED]
5. パフォーマンスの違いと注意点
操作速度の目安(平均ケース)
| 実装 | 追加 | 検索 | 削除 |
|---|---|---|---|
| HashSet | 速い(O(1)) | 速い(O(1)) | 速い(O(1)) |
| LinkedHashSet | やや遅い(O(1)) | やや遅い(O(1)) | やや遅い(O(1)) |
| TreeSet | 遅め(O(log n)) | 遅め(O(log n)) | 遅め(O(log n)) |
注意すべき点
- TreeSetはnullを追加するとNullPointerExceptionになる
- TreeSetにComparable未実装のクラスを追加するとClassCastExceptionになる
- HashSetは初期容量を指定しないと、再ハッシュで性能が落ちる可能性がある
6. よくあるミスとアンチパターン
- なんでもTreeSetを使ってしまう → 不必要に遅くなる
- nullをTreeSetに入れてエラー → TreeSetではnull禁止
- List感覚で順番期待してHashSetを使う → 順序は保証されない
- ジェネリクスを省略してしまう → 型安全が失われる
- スレッドセーフでないSetをマルチスレッドで使う → 同期の工夫が必要
7. まとめ:どのSetを選ぶ?フローチャートで確認!
↓ 要素の順序を保ちたい?
→ Yes:LinkedHashSet
→ No ↓
↓ 要素をソートして管理したい?
→ Yes:TreeSet
→ No ↓
↓ 高速に扱いたいだけ?
→ Yes:HashSet
→ No ↓
↓ enum型だけ扱いたい?
→ Yes:EnumSet
→ No:特殊なSetが必要(要件確認)
おわりに:Setを使いこなす力は「現場力」に直結!
Setは使い方を覚えるだけでなく、「適切に選ぶ」ことでコードの品質・性能・保守性が大きく変わります。
独学での習得が難しいと感じたら、まずは
👉 「絶対にJavaプログラマーになりたい人へ。」
でしっかり基礎を学びましょう。
さらに、
- ソースレビューがほしい
- 実務経験を積みたい
- プログラマー転職を本気で目指したい
という方には、サイゼントアカデミー が全力でサポートします!
次回は「Map系コレクションの選び方」も予定していますので、ぜひお楽しみに!


コメント