[英]Java HashMap containsKey strange behavior
試圖實現簡單的任務陷入奇怪的問題:
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
檢查都是真的。 進一步在代碼中它將被越來越多地使用。 所以首先要理解為什么它表現如此,如果可能的話修復它。 任何幫助贊賞。
Map的鍵是User
實例,因此a.containsKey("asd")
永遠不會返回true
,因為“asd”是一個String。
順便說一下,你沒有覆蓋Object
的equals
,它需要一個Object
參數。 這意味着a.containsKey(a2)
也返回false
,因為a1==a2
為false。
正確實現equals
將是:
@Override
public boolean equals(Object other){
if (!(other instanceof User))
return false;
User u = (User) other;
return this.login.equals(u.login);
}
正如Andy所提到的,你還必須覆蓋hashCode
,這樣如果a.equals(b)
為true,那么a.hashCode()==b.hashCode()
。
編輯:
我認為你可以使a.containsKey("asd")
返回true,如果你以一種將String
實例視為等於你的User
實例的方式覆蓋equals
,如果它們與login
屬性匹配:
@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
實現會違反Javadoc of Object
定義的equals
的合同,因為即使a1.equals("asd")
為真, "asd".equals(a1)
也會返回false。
編輯:
在檢查HashMap
的實現之后,我發現equals
這個實現將不起作用,因為containsKey(key)
的代碼將鍵與現有條目的鍵進行比較而不是相反的方式,並且String.equals(obj)
如果obj
不是String
它將始終返回false。 我想有一個很好的理由不打破equals
合同。
您需要覆蓋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;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.