1.hashCode()和equals() API hashCode()和equals()都來自上帝類Object, 所有的類都會擁有這兩個方法,特定時,覆寫它們。 它們是用來在同一類中做比較用的,尤其是在容器里如Set存放同一類對象時用來判斷放入的對象是否重覆。 下麵是API中的介紹: boole ...
1.hashCode()和equals() API
hashCode()和equals()都來自上帝類Object, 所有的類都會擁有這兩個方法,特定時,覆寫它們。
它們是用來在同一類中做比較用的,尤其是在容器里如Set存放同一類對象時用來判斷放入的對象是否重覆。
下麵是API中的介紹:
boolean equals (Object obj) :比較兩個對象是否相等。 equals方法在非空對象引用上實現等價關係: 自反性 :對於任何非空的參考值x , x.equals(x)應該返回true 。 對於任何非空引用值 x,x.equals(null) 都應返回 false。 Object 類的 equals 方法實現對象上差別可能性最大的相等關係;即,對於任何非空引用值 x 和 y,當且僅當 x 和 y 引用同一個對象時,此方法才返回 true(x == y 具有值 true)。 註意:當此方法被重寫時,通常有必要重寫 hashCode 方法,以維護 hashCode 方法的常規協定,該協定聲明相等對象必須具有相等的哈希碼。 |
int hashCode () :返回對象的哈希碼值。 支持此方法是為了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。 hashCode 的常規協定是: 在 Java 應用程式執行期間,在對同一對象多次調用 hashCode 方法時,必須一致地返回相同的整數,前提是將對象進行 equals 比較時所用的信息沒有被修改。 從某一應用程式的一次執行到同一應用程式的另一次執行,該整數無需保持一致。
實際上,由 Object 類定義的 hashCode 方法確實會針對不同的對象返回不同的整數。(這一般是通過將該對象的內部地址轉換成一個整數來實現的,但是 JavaTM 編程語言不需要這種實現技巧。) |
要點:
(1)equals()相等的兩個對象,hashcode()一定相等,equals()不相等的兩個對象,卻並不能證明它們的hashcode()不相等;
equals()方法不相等的兩個對象,hashCode()有可能相等。
(2)hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。
(3)在object類中,hashcode()方法是本地方法,返回的是本對象(單一對象)的地址值;而object類中的equals()方法比較的
也是兩個對象的地址值。如果equals()相等,說明兩個對象地址值也相等,hashcode()也就相等。
(4)當我們重寫一個對象的equals方法,通常有必要重寫它的hashCode方法。以維護 hashCode 方法的常規協定
equals()與==的比較
(1)'=='是用來比較兩個變數(基本類型和對象類型)的值是否相等的。 如果兩個變數是基本類型的,直接比較值就可以了。如果兩個變數是對象類型的,比較的是這兩個對象在棧中的引用(即地址)。
對象是放在堆中的,棧中存放的是對象的引用(地址)。由此可見'=='是比較棧中的值。如果要比較堆中對象的內容是否相同,那麼就要重寫equals方法了。
(2)Object類中的equals方法就是用'=='來比較的,所以如果沒有重寫equals方法,equals和==是等價的。
通常我們會重寫equals方法,讓equals比較兩個對象的屬性內容,而不是比較對象的引用(地址),因為往往我們覺得比較對象的內容是否相同比比較對象的引用(地址)更有意義。
2.HashCode的作用
在數據結構---哈希表中簡單介紹了散列表的原理,一句話就是:hash演算法提高了查找元素的效率。
如何查找一個集合中是否包含有某個對象呢?
一種方法是逐一取出每個元素與要查找的對象,使用equals方法比較的是否相等。如果一個集合中有很多個元素,則效率很慢。
HashCode在Java容器中的應用
對於List集合、數組而言,HashCode不重要,但是對於HashMap、HashSet、HashTable等而言,它變得異常重要。所以在使用HashMap、HashSet、HashTable時一定要註意hashCode。對於一個對象而言,其hashCode過程就是一個簡單的Hash演算法的實現,其實現過程對你實現對象的存取過程起到非常重要的作用。
一個對象肯定存在若幹個屬性,如何選擇屬性實現均勻散列(哈希表也稱為散列表,其要保持儘可能均勻,不重覆),考驗著一個人的設計能力。
如果我們將所有屬性進行散列,這必定會是一個糟糕的設計,因為對象的hashCode方法無時無刻不是在被調用,如果太多的屬性參與散列,那麼需要的操作數時間將會大大增加,這將嚴重影響程式的性能。
如果較少屬相參與散列,散列的多樣性會削弱,會產生大量的散列“衝突或碰撞”,除了不能夠很好的利用空間外,在某種程度也會影響對象的查詢效率。其實這兩者是一個矛盾體,散列的多樣性會帶來性能的降低。
3.覆寫(@Override)hashCode()和equals() 的慄子
public class Employee implements Comparable<Employee> { private String name; private int age; public Employee() { super(); } public Employee(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Emplooye [name=" + name + ", age=" + age + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Employee other = (Employee) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public int compareTo(Employee o) { int temp = this.age - o.age; return temp==0? this.name.compareTo(o.name):temp; } }
2018-01-07