HashMap の基本
名前で引きたいのに、端から順に見ている
商品名から価格を出す処理を List だけで書くと、こうなります。
Java
for (Item item : items) {
if (item.getName().equals("鉛筆")) {
return item.getPrice();
}
}1 件目で見つかることもあれば、最後まで見て見つからないこともあります。10 件なら気になりませんが、1 万件なら 1 万回の比較です。そもそも書きたかったのは鉛筆の値段であって、探す手順ではありません。
java.util.HashMap は、キーから値へ一発で飛ぶための入れ物です。辞書を先頭から読まずに見出しから引くのと同じで、件数が増えても取り出す速さがほとんど変わりません。
put で入れて、get で引く
Java
import java.util.HashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) {
Map<String, String> capitals = new HashMap<>();
capitals.put("日本", "東京");
capitals.put("フランス", "パリ");
System.out.println(capitals.get("日本")); // 東京
System.out.println(capitals.containsKey("ドイツ")); // false
System.out.println(capitals.size()); // 2
}
}Map<K, V> の山かっこは 2 つで、前がキーの型、後ろが値の型です。変数の型は HashMap ではなく Map にしておくのが一般的で、あとから別の実装に替えやすくなります。同じキーで 2 回 put すると、あとから入れた値で上書きされます。
無いキーを引くと null が返ってくる
get は、キーが無くても例外を投げずに null を返します。値が数値のときは、これが NullPointerException の入り口になります。
Java
Map<String, Integer> stock = new HashMap<>();
stock.put("鉛筆", 30);
int n = stock.get("消しゴム"); // null を int に変換できず落ちるInteger のまま受け取れば例外は出ませんが、そのあとの計算で結局つまずきます。防ぎ方は 2 つあり、containsKey で先に確かめてから get するか、getOrDefault で無かったときの値をその場で渡すかです。
Java
String city = capitals.getOrDefault("ドイツ", "不明"); // 不明getOrDefault はキーがあればその値を、無ければ第 2 引数をそのまま返します。分岐を書かずに済むので、既定値が決まっている場面ではこちらが読みやすくなります。
課題では、登録していない商品名を渡されたときに決まった値を返します。どちらの書き方でも通りますが、行数は getOrDefault のほうが短くなります。
要件
- クラス名は
Solution、メソッド名はpriceOf、引数はString item、戻り値の型はint - メソッド内で
HashMap<String, Integer>を作り、"apple"→100、"banana"→80、"cherry"→200の 3 件をputする - 存在するキーならその価格を返し、存在しないキーには必ず
-1を返すこと
入出力例
priceOf("apple") → 100
priceOf("banana") → 80
priceOf("cherry") → 200
priceOf("kiwi") → -1
priceOf("") → -1ヒント
編集 ゆめさく編集部