關於HashCode和equals方法在HashSet中的使用
Object類是類層次結構的根類,故所有的類都是先該類的方法,其中HashCode()和equals()方法也是該類的方法。
1.HashCode()方法
Object類中HashCode()方法實現如下:
public native int hashCode();
返回:該物件的雜湊值,可提高雜湊表的效能。
HashCode:
1.同一物件多次呼叫HashCode()方法,返回一直的整數,從某一程式的依次執行到同一程式的另一次執行,該整數無需保持一致;
2.使用equals(Object)方法兩個物件是相等的,那麼兩個物件返回的Hash值完全一致;
3. 使用equals(Object)方法兩個物件不相等,其返回的Hash值有可能相等。
下面摘錄API中String的HashCode()方法及相關屬性:
private final char value[];
private int hash; // Default to 0
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
給定一個字串,相當於在執行構造方法:
public String() {
this.value = new char[0];
}
此時,value值已經給定,此構造方法下value.length=0,顯然hash=h=0(預設值為0,也就是空字串),重在理解過程,雜湊演算法看API文件就好。
String s = new String();
System.out.Println(s.HashCode());
結果:0
2.equals()方法
Object類中equals()方法的實現如下:
public boolean equals(Object obj) {
return (this == obj);
}
指示其他某個物件是否與此物件引數相同,相同返回true,反之。equals()方法在非空物件引用(obj)上實現相等關係,對於任何非空引用值x,x.equals(null)都應返回false。String等類都會覆蓋Object類中的方法。
3.類HashSet
HashSet是Set介面的一個實現類,不能重複新增物件值,這個過程主要由Hash值和物件的equals()方法判斷,使用add()方法新增某種型別物件
//測試類
package com.test;
//測試類,該類重寫了從Object繼承而來的HashCode()和equals()方法
public class StudentTest {
private String name;
private int age;
public StudentTest(){}
public StudentTest(String name, int age){
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;
}
}
//HashSet類
package com.test;
import java.util.HashSet;
import java.util.Set;
public class SetDemo {
public static void main(String[] args) {
Set<StudentTest> set1 = new HashSet<>();
StudentTest s1 = new StudentTest("manu",10);
StudentTest s2 = new StudentTest("manu",10);
// set1.add(null);//此處null元素可以使用
set1.add(s1);
System.out.println(s1.hashCode());
set1.add(s2);
System.out.println(s2.hashCode());
System.out.println(set1.size());
}
}
執行結果:
794284386
779325750
2
上面s1、s2是兩個物件,每一次新增物件是hash值都不同,故該物件可以新增到HashSet中,其size=2,上面涉及到一個問題,某個物件的屬性一致,如果不想將屬性一致的物件再一次新增進去,則必須重寫StudentTest類的HashCode()方法和equals()方法,經過重寫兩者hash相同,在用equals方法來驗證,返回true,表示兩個物件重複,反之。程式碼如下:
@Override
public int hashCode() {
System.out.println("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) {
System.out.println("equals");//用於測試
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
StudentTest other = (StudentTest) 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;
}
此時執行結果如下:
hashCode
hashCode
3345234
hashCode
equals
hashCode
3345234
1
兩者不同的物件,屬性值一致,但不能新增到HashSet中,注意需求的變化。
在HashSet中新增元素時,若hash值不一致,則可以新增;若hash值一致,呼叫equals方法看物件是否相同,不同(false)則可以新增。注意equals判斷,某兩個物件不同,hash值可能相同,上述示例中hash值相同,但s1和s2是兩個不同物件。