IT

[Java]Mapのkeyに自作クラスを指定するときの注意

久々にJavaでプログラム書きました。

なかなか勘が鈍っているのか、Mapのkey操作ではまってしまったので、メモしておきます。

やりたいこと

Mapのkeyとvalueに自作クラスを使って、containsKey()やput()をしてみます。

こんな感じです。

Map templateMap = new HashMap<>();
class TemplateKey {
    private int key1;
    private int key2;
}
class TemplateValue {
    private int value1;
    private int value2;
}

ここまでは、簡単にできると思っていました。。

発生した問題

今考えると、「そりゃそうだよな」と思います。。

1つデータをputして、containsKey()でkeyを検索したがひっかからない。

containsKey()って引数がObject型で、intでもStringでも検索してくれるイメージでしたが、今回のような自作クラスのObjectだと、このままでは検索できないんですね。

Map templateMap = new HashMap<>();
TemplateKey key = new TemplateKey(1, 2);
TemplateKey value = new TemplateValue(3, 4);
templateMap.put(key, value);

// 検索するkey
TemplateKey searchKey = new TemplateKey(1, 2);

templateMap.containsKey(searchKey)  // false

TemplateKeyクラスのオブジェクトを新しく生成して、それをcontainsKey()の引数に指定するとfalseになります。

まあ、Stringの比較の時と同様に、オブジェクト比較になっているからなんでしょうね。。

put()やget()も同様に、今回やりたいことがオブジェクト比較によってできなくなっていました。

解決するためにやったこと

解決方法は簡単でした。

TemplateKeyクラスのequals()とhashCode()を、オーバーライドして処理を書き換えてあげれば解決できました。

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof TemplateKey) {
            TemplateKey condition = (TemplateKey) obj;
            return this.key1.equals(condition.key1) 
                    && this.key2.equals(condition.key2);
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return Objects.hash(key1, key2);
    }

-IT