はじめに:Setを知ればJavaがもっと得意になる!
「Javaでリストは使えるけど、Setってなんだろう?」
そんな疑問を持つ方は多いはずです。Set(セット)は、Javaで「重複しないデータの集まり」を表すとても大切なコレクションです。
このブログでは、Java初心者やこれからプログラマーを目指す方に向けて、「Set系コレクションの種類と選び方」をわかりやすく解説します。
転職を目指して学習中の方にも、「業務でどのSetを使えばよいか?」という実践的な判断ポイントが身につきますよ!
1. Setって何?どんなときに使うの?
✔ Setは「重複しない集合」
JavaのSetインターフェースは、要素の重複を許さないデータ構造です。
例えば、同じユーザーIDを2回登録したくないときなどに活躍します。
1 2 3 4 5 6 |
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、順番にこだわらないとき
1 2 3 4 5 6 |
Set<String> set = new HashSet<>(); set.add("apple"); set.add("banana"); set.add("apple"); // 無視 System.out.println(set); // 順序保証なし |
- 平均O(1)の高速な操作
- nullの追加OK(1つだけ)
② LinkedHashSet:順序を保ちたいならこれ!
- 特徴:順番あり、重複なし
- 使いどころ:「追加した順序」で要素を保持したいとき
1 2 3 4 5 |
Set<String> set = new LinkedHashSet<>(); set.add("apple"); set.add("banana"); System.out.println(set); // [apple, banana] |
- 内部構造は「ハッシュ表+双方向リスト」
- HashSetよりやや重いが、順序が大事な場面で重宝!
③ TreeSet:並び順も大事なら!
- 特徴:自動でソート、重複なし
- 使いどころ:常にソートされた状態を保ちたいとき
1 2 3 4 5 |
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のサンプル
1 2 3 4 5 6 |
Set<String> set = new HashSet<>(); set.add("one"); set.add("two"); set.add("one"); // 重複無視 System.out.println(set); // [one, two] 順序は不定 |
LinkedHashSetのサンプル
1 2 3 4 5 |
Set<String> set = new LinkedHashSet<>(); set.add("first"); set.add("second"); System.out.println(set); // [first, second] |
TreeSetのサンプル
1 2 3 4 5 |
Set<String> set = new TreeSet<>(); set.add("banana"); set.add("apple"); System.out.println(set); // [apple, banana] 自動ソート |
EnumSetのサンプル
1 2 3 4 |
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を選ぶ?フローチャートで確認!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
↓ 要素の順序を保ちたい? → Yes:LinkedHashSet → No ↓ ↓ 要素をソートして管理したい? → Yes:TreeSet → No ↓ ↓ 高速に扱いたいだけ? → Yes:HashSet → No ↓ ↓ enum型だけ扱いたい? → Yes:EnumSet → No:特殊なSetが必要(要件確認) |
おわりに:Setを使いこなす力は「現場力」に直結!
Setは使い方を覚えるだけでなく、「適切に選ぶ」ことでコードの品質・性能・保守性が大きく変わります。
独学での習得が難しいと感じたら、まずは
👉 「絶対にJavaプログラマーになりたい人へ。」
でしっかり基礎を学びましょう。
さらに、
- ソースレビューがほしい
- 実務経験を積みたい
- プログラマー転職を本気で目指したい
という方には、サイゼントアカデミー が全力でサポートします!
次回は「Map系コレクションの選び方」も予定していますので、ぜひお楽しみに!
コメント