參考:http://blog.csdn.net/hzw19920329/article/details/51944114
1、equals和==
equals的作用是用來判斷兩個對象是否相等,Java中所有的類都實作了equals方法。在equals沒有被重寫的情況下equals等價于==
==比較(這裡指對象比較)的是兩個對象是否是同一個對象
public class User {
private String username;
private String pass;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPass() {
return pass;
}
public void setPass(String pass) {
this.pass = pass;
}
public User(String username, String pass) {
super();
this.username = username;
this.pass = pass;
}
}
用==測試
public static void main(String[] args) {
User u1=new User("vivien","1234");
User u2=new User("vivien","1234");
System.out.println(u1==u2);
System.out.println(u1.equals(u2));
}
輸出
false
false
盡管變量都一樣,但是這兩個畢竟不是同一個對象,是以執行==時顯示false,而在沒有重寫equals的時候equals等價于==(String預設是重寫了equals的,是以執行equals的時候new兩個一樣的String用equals比較是true)
重寫equals:
public class User {
private String username;
private String pass;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPass() {
return pass;
}
public void setPass(String pass) {
this.pass = pass;
}
public User(String username, String pass) {
super();
this.username = username;
this.pass = pass;
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
if(obj==null)
return false;
if(obj==this)
return true;
if(obj instanceof User)
{
User o=(User)obj;
if(o.getUsername()==this.username && o.getPass()==this.pass)
return true;
else return false;
}
else
{
return false;
}
}
}
重新測試顯示:
false
true
可以發現重寫了equals之後輸出true
注意equals原則:
1. 對稱性:如果x.equals(y)傳回是”true”,那麼y.equals(x)也應該傳回是”true”。
2. 反射性:x.equals(x)必須傳回是”true”。
3. 類推性:如果x.equals(y)傳回是”true”,而且y.equals(z)傳回是”true”,那麼z.equals(x)也應該傳回是”true”。
4. 一緻性:如果x.equals(y)傳回是”true”,隻要x和y内容一直不變,不管你重複x.equals(y)多少次,傳回都是”true”。
5. 非空性,x.equals(null),永遠傳回是”false”;x.equals(和x不同類型的對象)永遠傳回是”false”。
2、equals和hashCode()
hashCode()的作用是擷取哈希碼,也稱為散列碼,傳回的是一個int整數。
這兩個如果不是在散清單中比較完全沒有意思。因為如果這個類不是放在散清單中,equals和hashCode()沒有半毛錢關系。
這裡我以hashMap來說兩者關系吧
HashMap解決沖突的方法時拉鍊法(把所有hashCode相同的鍵值對用單連結清單連接配接起來),這也導緻了HahMap的結構–數組+連結清單:
每個鍵值對在hashMap中是以Entry的形式存在
HashMap的put原理:
首先用hashCode()方法計算目前key的hash值,接着找到計算出來的hash值在數組中的下标位置,檢視該下标位置處對應的連結清單是否為null,為null的話直接将目前鍵值對插入到該連結清單首位。如果下标位置處對應的連結清單不為null的話,會使用for循環,每次循環通過key的equals()方法檢視這個連結清單中有沒有與目前鍵值對相等的Entry存在,有的話會用目前值替換原先這個鍵值對的value值,周遊結束如果不存在的話,會将目前鍵值對插入到連結清單頭部。
HashMap的get原理
get操作過程思想可以借助于put過程,首先會計算出目前key值的hash值,接着找到此hash值在數組中的位置,找到這個位置對應的連結清單,接着通過for循環周遊這個連結清單,周遊過程中調用equals方法檢視有沒有等于目前key的鍵值對存在,有的話直接傳回這個鍵值對對應的value值即可
是以HashMap 如果想要實作讓對象做key,并且相同變量的對象視為相同的key的話,一定要重寫equals()方法和hashCode()方法。什麼意思呢,直接看例子:
上面的User類如果我沒有重寫equals()方法和hashCode()方法,把User類作為key,存到HashMap中時:
public static void main(String[] args) {
Map<User,String> m=new HashMap<User,String>();
User u1=new User("vivien","1234");
User u2=new User("vivien","1234");
m.put(u1, "這是u1");
m.put(u2, "這是u2");
System.out.println("u1 hashCode():"+u1.hashCode());
System.out.println("u2 hashCode():"+u2.hashCode());
System.out.println("u1.equals(u2)?"+u1.equals(u2));
Set<Map.Entry<User, String>> entries=m.entrySet();
Iterator it=entries.iterator();
while(it.hasNext())
System.out.println(it.next());
}
輸出(為了輸出直覺,為在User中重寫了toString()方法):
u1 hashCode():1704856573
u2 hashCode():705927765
u1.equals(u2)?false
User [username=vivien, pass=1234]=這是u1
User [username=vivien, pass=1234]=這是u2
很顯然,u1和u2hashCode不一樣,并且也不equals,HashMap把u1和u2當做兩個key來對待
現在重寫equals和hashCode()方法:
public class User {
private String username;
private String pass;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPass() {
return pass;
}
public void setPass(String pass) {
this.pass = pass;
}
@Override
public String toString() {
return "User [username=" + username + ", pass=" + pass
+ "]";
}
public User(String username, String pass) {
super();
this.username = username;
this.pass = pass;
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
if(obj==null)
return false;
if(obj==this)
return true;
if(obj instanceof User)
{
User o=(User)obj;
if(o.getUsername()==this.username && o.getPass()==this.pass)
return true;
else return false;
}
else
{
return false;
}
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
return (this.username+this.pass).hashCode();
}
}
重新運作上面的test:
u1 hashCode():-1331478383
u2 hashCode():-1331478383
u1.equals(u2)?true
User [username=vivien, pass=1234]=這是u2
這時可以看到,在插入u2時,HashMap首先計算u2 hashCode,找到了與u1相同hashCode的鍊,在這個鍊中,通過for循環發現u1的key equals u2的key,是以把u2對應的value覆寫u1對應的value。是以最後周遊Map發現隻有一個鍵值對