マッ

マップ の Java

11個の演習

マップについて

Mapは、キーと値のペアを保存するためのデータ構造です。 他のプログラミング言語の辞書に似ています。 Mapインターフェースは、マップに対して行える操作を定義しています。

HashMap

Javaには、さまざまなMapの実装があります。 HashMapは、よく使われる実装の1つです。

// Make an instance
Map<String, Integer> fruitPrices = new HashMap<>();
Note

Map型の変数を定義するときは、上の例のように、具体的な型ではなくMap型として定義することをおすすめします。 そうしておくと、あとからMapの実装を変更しやすくなります。

HashMapにはコピーコンストラクターもあります。

// Make a copy of a map
Map<String, Integer> copy = new HashMap<>(fruitPrices);

マップに要素を追加するには、putを使います。

fruitPrices.put("apple", 100);
fruitPrices.put("pear", 80);
// => { "apple" => 100, "pear" => 80 }

1つのキーに紐づけられる値は1つだけです。 同じキーでputを呼び出すと、そのキーの値が更新されます。

fruitPrices.put("pear", 40);
// => { "apple" => 100, "pear" => 40 }

キーに対応する値を取得するには、getを使います。

fruitPrices.get("apple"); // => 100

マップに特定のキーが含まれているかどうかを調べるには、containsKeyを使います。

fruitPrices.containsKey("apple");   // => true
fruitPrices.containsKey("orange");  // => false

要素を削除するには、removeを使います。

fruitPrices.put("plum", 90);  // Add plum to map
fruitPrices.remove("plum");   // Removes plum from map

sizeメソッドは、要素の数を返します。

fruitPrices.size();  // Returns 2

keySetメソッドやvaluesメソッドを使うと、Mapのキーや値を、それぞれSetやコレクションとして取得できます。

fruitPrices.keySet();  // Returns "apple" and "pear" in a set
fruitPrices.values();  // Returns 100 and 80, in a Collection

HashMapはhashCodeとequalsを使う

HashMapは、オブジェクトのhashCodeメソッドとequalsメソッドを使って、キーの値をどこに保存し、どう取り出すかを決めます。 そのため、値を保存してから取り出すまでの間に、これらの戻り値が変わらないことが重要です。変わってしまうと、HashMapが値を正しく見つけられなくなることがあります。

たとえば、マップのキーとして使う次のようなクラスがあるとします。

public class Stock {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (Objects.equals(Stock.class, obj.getClass()) && obj instanceof Stock other) {
            return Objects.equals(name, other.name);
        }
        return false;
    }
}

hashCodeとequalsは、nameフィールドに依存しています。このフィールドはsetNameで変更できます。 hashCodeを変更すると、意外な結果になることがあります。

Stock stock = new Stock();
stock.setName("Beanies");

Map<Stock, Integer> stockCount = new HashMap<>();
stockCount.put(stock, 80);

stockCount.get(stock); // Returns 80

Stock other = new Stock();
other.setName("Beanies");

stockCount.get(other); // Returns 80 because "other" and "stock" are equal

stock.setName("Choccies");
stockCount.get(stock); // Returns null because hashCode value has changed

stockCount.get(other);  // Also returns null because "other" and "stock" are not equal

stock.setName("Beanies");
stockCount.get(stock); // HashCode restored, so returns 80 again

stockCount.get(other); // Also returns 80 again because "other" and "stock" are back to equal

Map.ofとMap.copyOf

マップを作成するもう1つの一般的な方法は、Map.ofやMap.ofEntriesを使うことです。

// Using Map.of
Map<String, Integer> temperatures = Map.of("Mon", 30, "Tue", 28, "Wed", 32);

// or using Map.ofEntries
Map<String, Integer> temperatures2 = Map.ofEntries(
    Map.entry("Mon", 30),
    Map.entry("Tue", 28),
    Map.entry("Wed", 32)
);

HashMapと違い、これらはあらかじめマップに値を入れて作成し、作成後は読み取り専用になります。 Map.copyOfは、マップの読み取り専用のコピーを作成します。

Map<String, Integer> readOnlyFruitPrices = Map.copyOf(fruitPrices);

put、remove、clearなどのメソッドを呼び出すと、UnsupportedOperationExceptionが発生します。

GitHubで編集 リンクは新しいウィンドウまたはタブで開きます

マップを学習する

練習はロックされています

マップを練習するには、あと1個の演習のロックを解除してください