试图将简单的任务陷入奇怪的问题:
class User{
String login;
String pwrd;
User(String lg,String pw){
this.login=lg;
this.pwrd=pw;
}
public String toString(){
return this.login;
}
public boolean equals(String a){
return this.login.equals(a);
}
public boolean equals(User t){
return this.login.equals(t.toString());
}
}
public class Foo{
public static void main (String[] args)
{
HashMap<User,Boolean> a=new HashMap<>();
User a1=new User("asd","123"),a2=new User("asd","134");
a.put(a1,false);
a.put(a2,false);
System.out.println(a.containsKey(a2));
System.out.println(a.containsKey("asd"));
}
}
结果我希望两个containsKey
检查都是真的。进一步在代码中它将被越来越多地使用。所以首先要理解为什么它表现如此,如果可能的话修复它。任何帮助表示赞赏。
答案 0 :(得分:7)
地图的键是User
个实例,因此a.containsKey("asd")
永远不会返回true
,因为“asd”是一个字符串。
顺便说一下,你没有覆盖Object
的{{1}},它需要一个equals
参数。这意味着Object
也会返回a.containsKey(a2)
,因为false
为false。
a1==a2
的正确实施将是:
equals
正如Andy所说,你还必须覆盖@Override
public boolean equals(Object other){
if (!(other instanceof User))
return false;
User u = (User) other;
return this.login.equals(u.login);
}
,这样如果hashCode
为真,那么a.equals(b)
。
编辑:
我认为,如果您以a.hashCode()==b.hashCode()
实例与a.containsKey("asd")
实例相等的方式覆盖equals
String
,如果它们与{User
匹配,则可以使login
返回true 1}} property:
@Override
public boolean equals(Object other){
if (other instanceof User) {
User u = (User) other;
return this.login.equals(u.login);
} else if (other instanceof String) {
String u = (String) other;
return this.login.equals(u);
}
return false;
}
@Override
public int hashCode()
{
return login.hashCode();
}
我从未尝试过equals
这样的实现,但根据我对HashMap
的理解,它可能有用。
但是,equals
的此类实施会违反equals
的Javadoc中定义的Object
合同,因为即使"asd".equals(a1)
a1.equals("asd")
将返回false是真的。
编辑:
在检查HashMap
的实现后,我发现equals
的这种实现不起作用,因为containsKey(key)
的代码将密钥与现有条目的密钥进行比较而不是反过来说,如果String.equals(obj)
不是obj
,String
将始终返回false。我想有一个很好的理由不打破equals
的合同。
答案 1 :(得分:1)
您需要覆盖public boolean equals(Object other)
并在该方法内部检查传递的其他对象的正确类型。请注意,传递的对象也可能为null 。
public class User {
public boolean equals(Object other) {
//Is the same
if(other == this) {
return true;
}
//Other is a user as well - Includes null-check (thanks, Kevin!)
if(other instanceof User) {
//equal if usernames are equal
return login.equals(other.login);
}
//anything else - not equal / null, whatever
return false;
}
}