Java入門 STEP18|Map・HashMapを学ぼう

karin@taishi@felmia

Map・HashMapとは?

STEP17では、ListやArrayListを使って複数のデータをまとめて管理する方法を学びました。

Listでは、データが順番に並んでいて、indexを使って取り出すことができます。

例えば、

names.get(0);

とすると、indexが0のデータを取得できます。

一方で、データによっては番号ではなく、名前などを指定して値を取り出したいこともあります。

例えば、

りんご → 150円
みかん → 120円
ぶどう → 300円

のように、「商品名」と「価格」を組み合わせて管理したい場合です。

このようなデータを扱うときに使えるのがMapです。

Mapとは?

データを「キー(key)」と「値(value)」の組み合わせで管理する仕組みです。

キーを指定することで、そのキーに対応する値を取得できます。

ルミィ
ルミィ

Listは番号で探してたけど、Mapなら「りんご」みたいな名前を使って探せるんだね♪

HashMapを作ってみよう

Mapを使うときによく利用されるクラスの1つがHashMapです。

まずは実際に作ってみます。

import java.util.HashMap;
import java.util.Map;

public class HashMapBasicSample {

    public static void main(String[] args) {

        Map<String, Integer> prices = new HashMap<>();

    }
}

注目するのは、

Map<String, Integer>

です。

STEP17のListでは、

List<String>

のように、扱うデータの型を1つ指定していました。

Mapでは、キーと値の2つの型を指定します。

今回の場合は、

String → 商品名
Integer → 価格

です。

そのため、

Map<String, Integer> prices

としています。

Mapの型の指定

Mapでは、

Map<キーの型, 値の型>

の順番で指定します。

例えば、

Map<String, Integer>

なら、String型のキーとInteger型の値を組み合わせて管理します。

put()でデータを追加する

Mapにデータを追加するときはput()を使います。

import java.util.HashMap;
import java.util.Map;

public class HashMapPutSample {

    public static void main(String[] args) {

        Map<String, Integer> prices = new HashMap<>();

        prices.put("りんご", 150);
        prices.put("みかん", 120);
        prices.put("ぶどう", 300);

        System.out.println(prices);
    }
}

Mapでは、

put(キー, 値)

という形でデータを追加します。

例えば、

prices.put(“りんご”, 150);

なら、

りんご → 150

という組み合わせが保存されます。

Listのadd()とは書き方が違うので、区別して覚えておきましょう。

get()で値を取得する

Mapから値を取得するときはget()を使います。

import java.util.HashMap;
import java.util.Map;

public class HashMapGetSample {

    public static void main(String[] args) {

        Map<String, Integer> prices = new HashMap<>();

        prices.put("りんご", 150);
        prices.put("みかん", 120);
        prices.put("ぶどう", 300);

        System.out.println(prices.get("りんご"));
        System.out.println(prices.get("ぶどう"));
    }
}

実行結果

150
300

Listでは、

names.get(0);

のようにindexを指定しました。

Mapでは、

prices.get("りんご");

のようにキーを指定します。

ListとMapのget()

List

names.get(0);

indexを使って取得します。

Map

prices.get("りんご");

キーを使って取得します。

どちらにもget()がありますが、指定するものが違います。

ルミィ
ルミィ

「りんごの値段が知りたい!」って、そのままキーを指定できる感じなんだね♪

同じキーをput()するとどうなる?

Mapでは、同じキーを複数持つことはできません。

例えば、

import java.util.HashMap;
import java.util.Map;

public class HashMapUpdateSample {

    public static void main(String[] args) {

        Map<String, Integer> prices = new HashMap<>();

        prices.put("りんご", 150);
        prices.put("りんご", 180);

        System.out.println(prices.get("りんご"));
    }
}

実行結果

180

最初に、

prices.put("りんご", 150);

としていますが、そのあとに同じ「りんご」というキーで、

prices.put("りんご", 180);

としています。

この場合、新しいデータが追加されるのではなく、「りんご」に対応する値が180に変更されます。

Mapのキーは重複しない

同じキーでput()すると、そのキーに対応する値が新しい値に置き換わります。

キーは、値を探すための目印になるものと考えておきましょう。

remove()でデータを削除する

Mapからデータを削除するときはremove()を使います。

import java.util.HashMap;
import java.util.Map;

public class HashMapRemoveSample {

    public static void main(String[] args) {

        Map<String, Integer> prices = new HashMap<>();

        prices.put("りんご", 150);
        prices.put("みかん", 120);
        prices.put("ぶどう", 300);

        prices.remove("みかん");

        System.out.println(prices);
    }
}

削除するときもindexではなく、キーを指定します。

prices.remove("みかん");

これで「みかん」と、それに対応する値がMapから削除されます。

containsKey()でキーがあるか確認する

Mapを使っていると、

「このキーは登録されている?」

と確認したいことがあります。

そんなときに使えるのがcontainsKey()です。

import java.util.HashMap;
import java.util.Map;

public class HashMapContainsSample {

    public static void main(String[] args) {

        Map<String, Integer> prices = new HashMap<>();

        prices.put("りんご", 150);
        prices.put("みかん", 120);

        System.out.println(prices.containsKey("りんご"));
        System.out.println(prices.containsKey("バナナ"));
    }
}

実行結果

true
false

「りんご」は登録されているのでtrue、「バナナ」は登録されていないのでfalseになります。

条件分岐と組み合わせることもできます。

import java.util.HashMap;
import java.util.Map;

public class HashMapCheckSample {

    public static void main(String[] args) {

        Map<String, Integer> prices = new HashMap<>();

        prices.put("りんご", 150);
        prices.put("みかん", 120);

        if (prices.containsKey("りんご")) {
            System.out.println("りんごは登録されています");
        }
    }
}

実行結果

りんごは登録されています

STEP4で学んだif文がここでも使えます。

size()でデータ数を調べる

Mapにいくつの組み合わせが入っているのかを確認するときは、Listと同じくsize()を使います。

import java.util.HashMap;
import java.util.Map;

public class HashMapSizeSample {

    public static void main(String[] args) {

        Map<String, Integer> prices = new HashMap<>();

        prices.put("りんご", 150);
        prices.put("みかん", 120);
        prices.put("ぶどう", 300);

        System.out.println(prices.size());
    }
}

実行結果

3

3組のデータが登録されているので、3が表示されます。

Mapのデータを繰り返し処理する

Mapに入っているデータをすべて処理したい場合もあります。

キーと値を両方使う場合は、entrySet()を利用できます。

import java.util.HashMap;
import java.util.Map;

public class HashMapLoopSample {

    public static void main(String[] args) {

        Map<String, Integer> prices = new HashMap<>();

        prices.put("りんご", 150);
        prices.put("みかん", 120);
        prices.put("ぶどう", 300);

        for (Map.Entry<String, Integer> entry : prices.entrySet()) {
            System.out.println(
                entry.getKey() + ":" + entry.getValue() + "円"
            );
        }
    }
}

表示される内容は次のようになります。

りんご:150円
みかん:120円
ぶどう:300円

※HashMapでは、データが必ずこの順番で取り出されるとは限りません。

ここでは新しく、

Map.Entry<String, Integer>

という書き方が出てきました。

Entryは、Mapに保存されているキーと値の1組を表します。

そして、

entry.getKey()

でキー、

entry.getValue()

で値を取得できます。

Mapを繰り返し処理する

for (Map.Entry<String, Integer> entry : prices.entrySet())

とすると、Mapに保存されているキーと値の組み合わせを1つずつ取り出せます。

最初は少し長く見えるので、書き方を一度ですべて覚える必要はありません。

HashMapでは順番を当てにしない

Listでは、データを追加した順番とindexが重要でした。

一方、HashMapでは、データの順番を前提にして扱いません。

例えば、

prices.put("りんご", 150);
prices.put("みかん", 120);
prices.put("ぶどう", 300);

という順番で追加しても、繰り返し処理したときに必ず、

りんご
みかん
ぶどう

の順番になるとは限りません。

ルミィ
ルミィ

Mapは「何番目?」より「このキーの値は?」って探すのが得意なんだね♪

順番が重要なデータならList、キーと値の対応が重要なデータならMapという違いを意識してみましょう。

MapとHashMapの違い

ここはSTEP17のListとArrayListに似ています。

Map<String, Integer> prices = new HashMap<>();

左側のMapはインターフェースです。

右側のHashMapは、Mapを実装しているクラスです。

そのため、インターフェース型で実装クラスのオブジェクトを扱っています。

STEP15のインターフェース、STEP16のポリモーフィズム、STEP17のListとArrayListで学んできた考え方が、ここでも使われています。

MapとHashMapの関係

Mapはインターフェースです。

HashMapはMapを実装したクラスです。

そのため、

Map<String, Integer> prices = new HashMap<>();

という書き方ができます。

ListとMapを使い分ける

最後に、STEP17のListと今回のMapの違いを整理します。

List

データを順番に管理したいときに使います。

0 → 田中
1 → 佐藤
2 → 鈴木

indexを使ってデータを取得できます。

Map

キーと値を組み合わせて管理したいときに使います。

りんご → 150
みかん → 120
ぶどう → 300

キーを使って値を取得できます。

例えば、

参加者の名前を順番に保存する → List

商品名と価格を対応させる → Map

と考えることができます。

どちらが優れているというものではなく、扱いたいデータに合わせて選びます。

よくある間違い

キーと値の順番を逆にする

Map<String, Integer> prices

なら、

Stringがキー、Integerが値です。

Map<キーの型, 値の型>

の順番で覚えましょう。

add()を使おうとする

Listでは、

names.add("田中");

でした。

Mapでは、

prices.put("りんご", 150);

を使います。

get()にindexを指定する

Mapでは、

prices.get("りんご");

のようにキーを指定します。

Listのget(0)とは意味が違います。

HashMapに順番があると思ってしまう

HashMapでは、追加した順番を前提に処理しないようにしましょう。

順番ではなく、キーと値の対応関係を管理するために使うと考えると分かりやすくなります。

STEP18のまとめ

STEP18のポイント

  • Mapはキーと値を組み合わせてデータを管理する
  • Map<キーの型, 値の型>の順番で型を指定する
  • put()でデータを追加する
  • get()でキーに対応する値を取得する
  • 同じキーでput()すると値が更新される
  • remove()でデータを削除できる
  • containsKey()でキーの存在を確認できる
  • size()でデータ数を確認できる
  • HashMapではデータの順番を前提にしない
  • Mapはインターフェース、HashMapはその実装クラス

最初は、「Listは順番、Mapはキーと値の組み合わせ」という違いを理解できれば大丈夫です。

ルミィ
ルミィ

STEP18クリア!
「商品名から価格を探す」みたいなデータなら、Mapが使いやすそうだね♪

次のSTEPへ

次のSTEPでは、プログラムを実行しているときに発生する「例外」について学びます。

例えば、数値に変換できない文字を数値へ変換しようとしたり、存在しないデータを扱おうとしたりすると、プログラムが正常に処理を続けられないことがあります。

Javaでは、このような問題を例外(Exception)として扱います。

そしてtry・catchを使うことで、例外が発生した場合の処理を書くことができます。

エラーが発生したら終わりではなく、問題が起きた場合にどう処理するのかを考えていきます。

→ STEP19「例外処理を学ぼう」

学習内容を確認したいときは、Java入門の一覧から各STEPを確認できます。

→ Java入門|初心者が基礎から学べるJava学習ガイド

記事URLをコピーしました