JavaのSet徹底ガイド:基本概念から活用法まで完全解説
CONTENTS
しかし「重複を防ぎたいだけなのに、どのSetを選べばいいのか分からない」と悩むことはありませんか。
JavaのSetは、重複排除を仕組みとして提供するコレクションで、IDやタグのように一意性が重要なデータ管理で力を発揮します。
本記事では、Setの基本概念から、HashSet・LinkedHashSet・TreeSetの違い、equals/hashCodeの注意点、Listとの相互変換、Stream活用までを体系的に解説します。
JavaにおけるSetとは?Listとの違いを押さえる
まずSetは、重複要素を一切許容しないCollectionインターフェースです。同じ要素を複数回追加しようとしても、2回目以降は登録されません。
そのため、Setは「集合」としての性質を持ち、データの一意性を自然に担保できます。
Setが向いている場面
例えば、ユーザーIDの重複登録防止、タグ管理、処理済みデータの記録など、一意性が求められるケースではSetが最適です。
Listとの違いは「重複」と「順序」
一方でListは、重複を許容し、インデックスによる順序管理を前提とします。順番に意味がある処理や、同じ値を複数保持したい場合はListが適しています。
Setの代表実装:HashSet/LinkedHashSet/TreeSetの使い分け
Setには複数の実装クラスがありますが、実務で主に使われるのはHashSet、LinkedHashSet、TreeSetの3つです。
HashSet:順序不要で高速に扱いたい場合
HashSetは、要素の順序を保証しない代わりに、高速な検索・追加・削除が可能です。順番に意味がなく、大量データを扱う場面に向いています。
LinkedHashSet:挿入順を保持したい場合
LinkedHashSetは、HashSetの特性に加えて、要素の挿入順を保持します。入力順をそのまま維持したい場合に便利ですが、HashSetよりメモリ消費は増えます。
TreeSet:常にソートされた状態で扱いたい場合
TreeSetは、要素を常にソートされた状態で保持します。自然順序またはComparatorで定義した順序に基づき、昇順・降順で管理できます。
ただし、HashSet系よりも追加・削除のコストは高くなるため、用途を選びます。
equalsとhashCodeがSetの挙動を左右する
Setの重複判定は、equalsメソッドとhashCodeメソッドに依存します。これらが正しく実装されていないと、意図しない重複や登録漏れが発生します。
ドメインオブジェクトでの注意点
例えばUserクラスをSetで管理する場合、「何を同一とみなすか」を明確にし、それをequalsとhashCodeに反映させる必要があります。
nullの扱いに注意
Setがnullを許容するかどうかは実装依存です。特にTreeSetでは、自然順序を使う場合にnullを追加すると例外が発生するため注意が必要です。
Set操作の基本メソッド
Setの基本操作はadd、remove、containsの3つです。addは追加可否をbooleanで返すため、重複チェックを簡潔に書けます。
ListとSetの相互変換
実務では、Listから重複を排除するためにSetへ変換し、処理後に再びListへ戻すケースがよくあります。
ListからSetへの変換
List<String> list = Arrays.asList("java", "set", "java");
Set<String> set = new HashSet<>(list);
SetからListへの変換
Set<String> set = new LinkedHashSet<>();
set.add("b");
set.add("a");
List<String> list = new ArrayList<>(set);
SetのループとStream活用
Setの走査には拡張for文、Iterator、Stream APIが使えます。特にStreamは、絞り込みや変換、集計を宣言的に書けるため、可読性と保守性が向上します。
Set<String> tags = new HashSet<>(Arrays.asList("java", "set", "list", "stream"));
List<String> filtered = tags.stream()
.filter(s -> s.startsWith("s"))
.sorted()
.collect(java.util.stream.Collectors.toList());
まとめ:用途に応じて最適なSetを選ぼう
Setは、重複排除を安全に実装できる強力なコレクションです。高速性重視ならHashSet、順序保持ならLinkedHashSet、ソートが必要ならTreeSetと使い分けましょう。
equalsとhashCodeの設計、順序やnullの扱いを意識することで、Setをより安全かつ効果的に活用できます。
つまずいたら、現役エンジニアと一緒に解決しよう
この記事で扱ったJavaは、独学だと細部で詰まりやすい分野です。実務レベルまで理解を深めたい方は、Zerocodeで学習を進めてみませんか。