dmo*_*221 19 java equals hashmap hashcode
我似乎在标准的Java HashMap中获得了重复的键.通过"复制",我的意思是键的equals()
方法相同.这是有问题的代码:
import java.util.Map;
import java.util.HashMap;
public class User {
private String userId;
public User(String userId) {
this.userId = userId;
}
public boolean equals(User other) {
return userId.equals(other.getUserId());
}
public int hashCode() {
return userId.hashCode();
}
public String toString() {
return userId;
}
public static void main(String[] args) {
User arvo1 = new User("Arvo-Part");
User arvo2 = new User("Arvo-Part");
Map<User,Integer> map = new HashMap<User,Integer>();
map.put(arvo1,1);
map.put(arvo2,2);
System.out.println("arvo1.equals(arvo2): " + arvo1.equals(arvo2));
System.out.println("map: " + map.toString());
System.out.println("arvo1 hash: " + arvo1.hashCode());
System.out.println("arvo2 hash: " + arvo2.hashCode());
System.out.println("map.get(arvo1): " + map.get(arvo1));
System.out.println("map.get(arvo2): " + map.get(arvo2));
System.out.println("map.get(arvo2): " + map.get(arvo2));
System.out.println("map.get(arvo1): " + map.get(arvo1));
}
}
Run Code Online (Sandbox Code Playgroud)
这是结果输出:
arvo1.equals(arvo2): true
map: {Arvo-Part=1, Arvo-Part=2}
arvo1 hash: 164585782
arvo2 hash: 164585782
map.get(arvo1): 1
map.get(arvo2): 2
map.get(arvo2): 2
map.get(arvo1): 1
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,equals()
两个User
对象上的方法是返回的true
,它们的哈希码是相同的,但它们各自形成一个不同key
的map
.此外,map
继续区分User
最后四个get()
呼叫中的两个键.
这直接与文档相矛盾:
更正式地说,如果此映射包含从键k到值v的映射,使得(key == null?k == null:key.equals(k)),则此方法返回v; 否则返回null.(最多可以有一个这样的映射.)
这是一个错误吗?我在这里错过了什么吗?我正在运行Java版本1.8.0_92,我通过Homebrew安装.
编辑:这个问题已被标记为另一个问题的副本,但我会留下这个问题,因为它确定了一个看似不一致equals()
的问题,而另一个问题假设错误在于hashCode()
.希望这个问题的存在将使这个问题更容易搜索.
Sve*_*rev 28
问题在于你的equals()
方法.签名Object.equals()
是equals(OBJECT)
,但在你的情况下它是equals(USER)
,所以这是两个完全不同的方法,并且hashmap调用带Object
参数的方法.您可以通过在@Override
等号上添加注释来验证它- 它将生成编译器错误.
equals方法应该是:
@Override
public boolean equals(Object other) {
if(other instanceof User){
User user = (User) other;
return userId.equals(user.userId);
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
作为最佳实践,您应该始终@Override
使用您覆盖的方法 - 它可以为您节省很多麻烦.
mid*_*dor 13
您的equals方法不会覆盖equals
,并且其中的类型在Map
运行时被擦除,因此实际的equals方法被称为equals(Object)
.你的平等应该看起来更像这样:
@Override
public boolean equals(Object other) {
if (!(other instanceof User))
return false;
User u = (User)other;
return userId.equals(u.userId);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2011 次 |
最近记录: |