Language
equals と hashCode: HashSetで値を見つけるための契約
equals が等しいオブジェクトは、同じ hashCode を返さなければ集合検索の契約を満たせません。
SourceUserId.java
Java 21
package examples.equality;
import java.util.Objects;
public final class UserId {
private final String value;
public UserId(String value) {
this.value = value;
}
@Override
public boolean equals(Object other) {
return other instanceof UserId userId && value.equals(userId.value);
}
@Override
public int hashCode() {
return Objects.hash(value);
}
}TestUserIdTest.java
Java 21
package examples.equality;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.HashSet;
import org.junit.jupiter.api.Test;
class UserIdTest {
@Test
void equalsで等しい値は同じhashCodeを返す() {
var first = new UserId("u-42");
var second = new UserId("u-42");
assertEquals(first, second);
assertEquals(first.hashCode(), second.hashCode());
}
@Test
void equalsとhashCodeを実装した値はHashSetで検索できる() {
var users = new HashSet<UserId>();
users.add(new UserId("u-42"));
assertTrue(users.contains(new UserId("u-42")));
}
}01Assertion
このテストで確認できること
- equals が true の値は同じ hashCode を返す
- 別インスタンスでも HashSet の contains で見つかる
equals だけを実装すると、HashSet や HashMap で期待どおりに振る舞いません。値オブジェクトでは両方を一緒に実装します。
OBSERVED RESULT
expected: HashSet.contains(new UserId("u-42")) → true
actual: true