Java 基礎からマスターまで — 第5回
ジェネリックとコレクションを目的に合わせて選択する
本ブログ作成文は、講義を目指して製作されました。 また、作成された文章の情報も間違っている可能性がありますので、ご注意ください。
Javaコレクションは複数のデータを保存しますが、データ構造ごとにうまくいくことが異なります。 ジェネリックを一緒に使用すると、取り出した値を毎回型変換せずに型エラーをコンパイルするときに確認することができる。
List, Set, Map
List<String> party = new ArrayList<>();
Set<Integer> unlockedIds = new HashSet<>();
Map<Integer, Item> itemById = new HashMap<>();
party.add("Rose");
unlockedIds.add(10);
itemById.put(10, new Item(10, "Potion"));
Listは順序と重複を許可し、Setは重複しない値が存在するかどうかを扱います。 Mapはキーを介して値を探します。
HashMapの順序は保証されません。 ソートまたは入力順序が契約の場合は、その目的に合った実装を選択する必要があります。
安全に検索
Item item = itemById.get(10);
if (item != null) {
System.out.println(item.getName());
}
getはキーがなければnullを返します。 null自体を値として格納する設計を避けると、なしとnull値を混同しないようになる。
ジェネリッククラス
public final class Registry<T extends Identifiable> {
private final Map<Integer, T> values = new HashMap<>();
public void add(T value) {
values.put(value.getId(), value);
}
public Optional<T> find(int id) {
return Optional.ofNullable(values.get(id));
}
}
T extends Identifiableは、保存するタイプがIDを提供する必要があるという制約です。 Registry<Item>とRegistry<Monster>は同じ規則を再利用しますが、値は混在しません。
実装よりもインタフェースに頼る
フィールドとパラメータタイプをListまたはMapインタフェースに置くと、必要な動作だけが契約に残ります。 しかし、パフォーマンス特性が重要な場合は、実際の実装がArrayListなのかLinkedListなのかを知っておく必要があります。
コレクションの選択はデータ数だけの問題ではありません。 順序、重複、検索キー、変更頻度という使用目的を先に決めなければならない。