Collections
HashMap: 可変のキーを変更すると登録済みの値を検索できない
hashCodeに使う状態を変更すると、HashMapが値を置いたバケットと検索先が一致しなくなります。
SourceMutableMapKeys.java
Java 21
package examples.map;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public final class MutableMapKeys {
private MutableMapKeys() {}
public static Map<Key, String> mapWith(Key key) {
Map<Key, String> values = new HashMap<>();
values.put(key, "stored");
return values;
}
public static final class Key {
private String value;
public Key(String value) {
this.value = value;
}
public void changeTo(String value) {
this.value = value;
}
@Override
public boolean equals(Object other) {
return other instanceof Key key && value.equals(key.value);
}
@Override
public int hashCode() {
return Objects.hash(value);
}
}
}TestMutableMapKeysTest.java
Java 21
package examples.map;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import org.junit.jupiter.api.Test;
class MutableMapKeysTest {
@Test
void HashMapへ登録した後にキーを変更すると同じキーで検索できない() {
var key = new MutableMapKeys.Key("draft");
var values = MutableMapKeys.mapWith(key);
key.changeTo("published");
assertFalse(values.containsKey(key));
assertNull(values.get(key));
}
}01Assertion
このテストで確認できること
- 登録後にキーのhashCodeへ影響する値を変更する
- 同じキーインスタンスでもcontainsKeyとgetで検索できなくなる
HashMapのキーには、登録後にequals・hashCodeが変わらない値を使います。可変オブジェクトはキーにせず、不変のIDやrecordを選びます。
OBSERVED RESULT
expected: containsKey(changed key) → false
actual: false
expected: get(changed key) → null