为什么自定义对象不等于 HashMap 的键?
我在使用自己的类作为 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));
}
}
I'm having trouble using my own class as a key for a 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;
}
}
Here is a failing JUnit test
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));
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您需要更改
为
每日提示:始终使用
@Override
注释。如果您使用了
@Override
注释,编译器会捕获错误并说:You need to change
to
Tip of the day: Always use
@Override
annotation.If you had used the
@Override
annotation, the compiler would have caught the error and said:您的代码是正确的,但您还需要重写从
Object
继承的equals
方法。将其添加到您的
ActorId
类中:Your code is correct, but you also need to override the
equals
method inherited fromObject
.Add this to your
ActorId
class:您绝对必须重写方法 equals(Object),并且对于 Map (HashMap) 的某些实现,还需要重写方法 hashCode()。
我遇到了同样的问题,如果没有自定义 hashCode 实现,则永远不会调用类“ActorId”的 equals 方法。
You definitely must override the method equals(Object), and for certain implementation of a Map (HashMap) it is also necesary that you overrdide the method hashCode().
I had the same problem, and without the custom hashCode implementation the equals method of the class "ActorId" was never called.
默认情况下,Java 调用 boolean
equals(Object obj);
因此,您登录是正确的,但如果您想覆盖 equals() 使用 Object 作为参数,并通过
instanceOf
或getClass()
检查类并进行类转换。By default Java invokes boolean
equals(Object obj);
So, you login is correct but if you want to OVERRIDE equals() use Object as a parameter and and check the class by
instanceOf
orgetClass()
and do a class casting.