Java アドバンス

Java HashMap

HashMap は、アイテムを「キー・バリュー・ペア(キーと値のペア)」として保存し、各キーが特定の値にマッピングされるデータ構造です。

java.util パッケージに含まれており、Map インターフェースを実装しています。

ArrayList のようにインデックス(添字)を使用して要素にアクセスするのではなく、キーを使用して関連付けられたを取得するのが特徴です。

HashMap では、以下のような様々な組み合わせを格納できます:

  • String 型のキーと Integer 型の値
  • String 型のキーと String 型の値

1. HashMap の作成

String 型のキーと String 型の値を格納する、capitalCities という名前の HashMap オブジェクトを作成する例です。

1.1 作成の例

import java.util.HashMap; // HashMap クラスをインポート

HashMap<String, String> capitalCities = new HashMap<>();

作成後は、put() を使ったペアの追加、get() を使ったキーによる値の取得、remove() を使ったエントリの削除などが可能です。これらはすべてインデックス番号ではなく、キーを使用して操作します。

2. 要素の追加

HashMap にアイテムを追加するには、put() メソッドを使用します。

2.1 追加のコード例

// HashMap クラスをインポート
import java.util.HashMap;

public class Main {
  public static void main(String[] args) {
    // capitalCities という名前の HashMap オブジェクトを作成
    HashMap<String, String> capitalCities = new HashMap<String, String>();

    // キーと値(国, 都市)を追加
    capitalCities.put("England", "London");
    capitalCities.put("India", "New Dehli");
    capitalCities.put("Austria", "Wien");
    capitalCities.put("Norway", "Oslo");
    capitalCities.put("Norway", "Oslo"); // 重複
    capitalCities.put("USA", "Washington DC");

    System.out.println(capitalCities);
  }
}

注意: 上記の例で、同じキー(例: "Norway")を複数回追加した場合、HashMap のキーはユニークである必要があるため、最新の値が以前の値を上書きします。

3. 要素へのアクセス

HashMap 内の値にアクセスするには、get() メソッドを使用し、そのキーを指定します。

3.1 アクセスの例

capitalCities.get("England");

4. 要素の削除

アイテムを削除するには、remove() メソッドを使用してキーを指定します。

4.1 削除の例

capitalCities.remove("England");

すべてのアイテムを削除するには、clear() メソッドを使用します。

4.2 全削除の例

capitalCities.clear();

5. HashMap のサイズ取得

アイテムがいくつあるかを確認するには、size() メソッドを使用します。

5.1 サイズ確認の例

capitalCities.size();

注意: サイズはユニークなキーの数のみをカウントします。同じキーが複数回追加された場合、最新の値のみが保持されます。

6. HashMap のループ処理

for-each ループを使用して HashMap のアイテムをループ処理できます。

注意: キーだけが必要な場合は keySet() メソッドを、値だけが必要な場合は values() メソッドを使用します。

6.1 キーをプリントする例

// キーを表示
for (String i : capitalCities.keySet()) {
  System.out.println(i);
}

6.2 値をプリントする例

// 値を表示
for (String i : capitalCities.values()) {
  System.out.println(i);
}

6.3 キーと値を両方プリントする例

// キーと値を表示
for (String i : capitalCities.keySet()) {
  System.out.println("key: " + i + " value: " + capitalCities.get(i));
}

7. 他のデータ型(ラッパークラス)の利用

HashMap のキーと値は実際にはオブジェクトです。これまでの例では String 型のオブジェクトを使用してきました。Java において String はオブジェクト(プリミティブ型ではない)であることを思い出してください。

int などの他の型を使用するには、対応するラッパークラスInteger など)を指定する必要があります。他のプリミティブ型については、boolean には Booleanchar には Characterdouble には Double などを使用します。

7.1 String のキーと Integer の値を持つ HashMap の例

// HashMap クラスをインポート
import java.util.HashMap;

public class Main {
  public static void main(String[] args) {

    // people という名前の HashMap オブジェクトを作成
    HashMap<String, Integer> people = new HashMap<String, Integer>();

    // キーと値(名前, 年齢)を追加
    people.put("John", 32);
    people.put("Steve", 30);
    people.put("Angie", 33);

    for (String i : people.keySet()) {
      System.out.println("key: " + i + " value: " + people.get(i));
    }
  }
}

8. 順序が重要な場合

次章では、キーによってソートされた順序でキー・バリュー・ペアを格納する TreeMap について学習します。

9. var キーワード

Java 10 以降では、型を2回記述することなく var キーワードを使用して HashMap 変数を宣言できます。コンパイラは代入された値から型を推論します。

これによりコードは短くなりますが、多くの開発者は依然として明確さのためにフルタイプ(完全な型名)を使用します。var は有効な Java の構文であるため、他のコードで見かける機会もあるでしょう。そのため、その存在を知っておくことは有用です。

9.1 var を使用した例

// var を使用しない場合
HashMap<String, String> capitalCities = new HashMap<String, String>();

// var を使用する場合
var capitalCities = new HashMap<String, String>();

10. Map インターフェース

注意: Java のコードでは、次のように MapHashMap の両方が使われているのをよく目にします。

10.1 インターフェースを用いた宣言例

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

Map<String, String> capitalCities = new HashMap<>();

これは、変数(capitalCities)が Map(インターフェース)として宣言され、そこに HashMap オブジェクト(実際のマップ)を格納していることを意味します。HashMapMap インターフェースを実装しているため、このような記述が可能です。