我在使用自己的类作为HashMap的键时遇到了麻烦
public class ActorId {
private final int playerId;
private final int id;
ActorId(int playerId, int id) {
this.playerId = playerId;
this.id = id;
}
public boolean equals(ActorId other) {
return this.id == other.id && this.playerId == other.playerId;
}
public int hashCode() {
int hash = 1;
hash = hash * 31 + playerId;
hash = hash * 31 + id;
return hash;
}
public String toString() {
return "#" + playerId + "." + id;
}
public int getPlayerId() {
return playerId;
}
}
这是一个失败的JUnit测试
import static org.junit.Assert.*;
import java.util.Map;
import org.junit.Test;
public class ActorIdTest {
@Test
public final void testAsMapKey() {
ActorId a = new ActorId(123, 345);
ActorId b = new ActorId(123, 345);
assertTrue(a.equals(b));
assertEquals(a.hashCode(), b.hashCode());
// Works with strings as keys
Map<String, String> map1 = new java.util.HashMap<String, String>();
map1.put(a.toString(), "test");
assertEquals("test", map1.get(a.toString()));
assertEquals("test", map1.get(b.toString()));
assertEquals(1, map1.size());
// But not with ActorIds
Map<ActorId, String> map2 = new java.util.HashMap<ActorId, String>();
map2.put(a, "test");
assertEquals("test", map2.get(a));
assertEquals("test", map2.get(b)); // FAILS here
assertEquals(1, map2.size());
map2.put(b, "test2");
assertEquals(1, map2.size());
assertEquals("test2", map2.get(a));
assertEquals("test2", map2.get(b));
}
}
答案 0 :(得分:9)
您需要更改
public boolean equals(ActorId other) {
....
}
到
public boolean equals(Object other) {
....
}
当天的提示:始终使用@Override
注释。
如果您使用了@Override
注释,编译器会发现错误并说:
ActorId类型的方法equals(ActorId)必须覆盖或实现超类型方法
答案 1 :(得分:3)
您的代码是正确的,但您还需要覆盖从equals
继承的Object
方法。
将此添加到您的ActorId
课程:
@Override
public boolean equals(Object other) {
if(other == null || other.getClass() != getClass())
return false;
return equals((ActorId)other);
}
答案 2 :(得分:1)
你肯定必须覆盖equals(Object)方法,对于Map(HashMap)的某些实现,你必须覆盖方法hashCode()。
我遇到了同样的问题,如果没有自定义hashCode实现,则从未调用类“ActorId”的equals方法。
答案 3 :(得分:0)
默认情况下,Java调用布尔值equals(Object obj);
因此,您登录是正确的但是如果您想要OVERRIDE equals()使用Object作为参数,并通过instanceOf
或getClass()
检查类并进行类转换。
if (obj instanceOf ActorId) {
ActorId other = (ActorId)obj;
... compare fields
}