Java相關(guān)規(guī)定
Java對于eqauls方法和hashCode方法是這樣規(guī)定的:
(1)如果兩個對象相同(equals方法返回true),那么它們的hashCode值一定要相同
(2)如果兩個對象的hashCode相同,它們并不一定相同
當(dāng)然,你未必要按照要求去做,但是如果你違背了上述原則就會發(fā)現(xiàn)在使用容器時,相同的對象可以出現(xiàn)在Set集合中,同時增加新元素的效率會大大下降(對于使用哈希存儲的系統(tǒng),如果哈希碼頻繁的沖突將會造成存取性能急劇下降)。
不遵循規(guī)定產(chǎn)生的后果
如果你自定義了一個對象,重寫了equals方法,但沒有重寫hashcode方法,那么此時的equals為true但是hashcode為false,就會產(chǎn)生奇怪的現(xiàn)象。
package com.denk;
import java.util.HashSet;
import java.util.Set;
/**
* @author: denk
* desc:
* date: 2018/3/23
*/
public class Person {
public int age;
public String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public boolean equals(Object obj) {
Person p = (Person) obj;
return p.age == this.age && p.name.equals(this.name);
//return super.equals(obj);
}
public static void main(String[] args) {
Person a = new Person(1, "mike");
Person b = new Person(1, "mike");
System.out.println(a.hashCode() + "###" + b.hashCode());
System.out.println(a.equals(b));//打印為true
Set<Person> set = new HashSet<>();
set.add(a);
set.add(b);
System.out.println(set.size());//打印2
}
}
如上代碼,重寫了equals但沒有重寫hashcode,造成的結(jié)果就是在使用equals比較時兩個對象是相等的。奇怪的現(xiàn)象產(chǎn)生了,因為set的size是2,說明兩個相等的對象被添加到set中了。
所以在重寫equals時一定要遵循Java的規(guī)定,同時重寫hashcode
遵循規(guī)定同時重寫equals和hashcode
package com.denk;
import java.util.HashSet;
import java.util.Set;
/**
* @author: denk
* desc:
* date: 2018/3/23
*/
public class Person {
public int age;
public String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public int hashCode() {
return 31 * this.age;
//return super.hashCode();
}
@Override
public boolean equals(Object obj) {
Person p = (Person) obj;
return p.age == this.age && p.name.equals(this.name);
//return super.equals(obj);
}
public static void main(String[] args) {
Person a = new Person(1, "mike");
Person b = new Person(1, "mike");
System.out.println(a.hashCode() + "###" + b.hashCode());
System.out.println(a.equals(b));//打印為true
Set<Person> set = new HashSet<>();
set.add(a);
set.add(b);//將會添加失敗
System.out.println(set.size());//打印1
}
}