今回やること
HashSetは、同じ値を重複して保存しない集合です。イベントの参加者名を一つのHashSetで管理します。
前提: Java入門 #17 - HashMapまでのコレクションと拡張for文を理解していること。
| 操作 | 戻り値・結果 |
|---|---|
add(value) | 新しく追加できればtrue、既存ならfalse |
contains(value) | 含まれていればtrue |
remove(value) | 削除できればtrue |
size() | 重複を除いた現在の件数 |
ArrayListとの一番大きな違いは、順番ではなく「その値が集合に含まれるか」を中心に扱う点です。
| 確認したいこと | 向くコレクション |
|---|---|
| 何番目に何があるか | ArrayList |
| 同じ値を1件だけ持つか | HashSet |
| ある値を含むか | HashSet |
受付順を残したい参加者一覧ならArrayList、参加済みかを素早く確認したい名前の集合ならHashSet、というように目的から選びます。
1. 名前を追加する
HashSet<String> participants = new HashSet<>();
participants.add("Ada");
participants.add("Ken");
participants.add("Mika");
HashSetにはindexがありません。get(0)のような取得はできず、繰り返す時の順番も保証されません。
変数の型をインターフェースのSetにする書き方もよく使われます。
Set<String> participants = new HashSet<>();
この場合はimport java.util.Set;も必要です。完成例では初学者が実体の型を追いやすいよう、左右ともHashSetにそろえています。
2. 重複を追加してみる
addの戻り値を見ると、追加されたかを判定できます。
boolean added = participants.add("Ada");
System.out.println(added); // すでにあるのでfalse
2回目のAdaは保存されず、件数も増えません。重複を検出したい時は、size()を前後で比べるよりaddの戻り値を使えます。
| 操作 | addの戻り値 | 保存される集合 | size |
|---|---|---|---|
| Adaを追加 | true | Ada | 1 |
| Kenを追加 | true | Ada, Ken | 2 |
| Adaを再追加 | false | Ada, Ken | 2 |
表では読みやすく並べていますが、実際のHashSetの列挙順を表すものではありません。
完成コードを動かす
HashSetDemo.javaとして保存します。
import java.util.HashSet;
public class HashSetDemo {
public static void main(String[] args) {
HashSet<String> participants = new HashSet<>();
System.out.println("Adaを追加: " + participants.add("Ada"));
participants.add("Ken");
participants.add("Mika");
System.out.println("Adaを再追加: " + participants.add("Ada"));
System.out.println("Kenがいる: " + participants.contains("Ken"));
participants.remove("Mika");
System.out.println("参加者数: " + participants.size());
for (String name : participants) {
System.out.println(name);
}
}
}
javac HashSetDemo.java
java HashSetDemo
最後の名前の表示順は環境によって変わっても正常です。順番が必要なデータには、HashSetを選びません。
contains("Ken")は、全件を表示して人が探す代わりに、集合へ存在を問い合わせます。ログイン済みID、選択済みタグ、処理済みファイル名など、「すでにあるか」が重要な場面で同じ考え方を使えます。
成功確認
次の4点を確認してください。
- 最初の
Ada追加はtrue - 2回目の
Ada追加はfalse KenがいるはtrueMikaを削除した後の参加者数は2
最後に表示される名前はAdaとKenですが、順番は問いません。
よくあるつまずき
表示順を期待する
HashSetは順序を保証しません。追加順が必要ならLinkedHashSet、並べ替えが必要なら用途に応じて別の方法を検討します。
自作クラスの重複を値で判定できない
Stringは内容で同一性を判定できます。自作クラスをHashSetへ入れる場合は、equalsとhashCodeの設計が必要です。これは後のオブジェクト指向学習で扱います。
Listと同じようにindexで読む
HashSetにget(index)はありません。「含むか」をcontainsで調べる用途に向きます。
addの戻り値を無視する
追加できなかったこと自体が重要な場合があります。重複申込みなどを検知したい時は、if (!set.add(value))のように戻り値を判定へ使います。
練習
アンケートで選ばれた色を入れるHashSet<String>を作ります。blue、red、blueの順で追加し、重複しない件数とredを含むかを表示してください。
次のステップ
Java入門 #19 - 例外処理の基本で、処理に失敗した時の扱いを学びます。