在集合框架中,set接口是以保證元素的唯一性而出名的,在實際開發中,set接口也很廣泛的應用,在set接口中hashset是非常常用的一種實現類.
那麼今天講一下hashset是如何保證的元素唯一.
hashset存儲自定義類型 保證元素唯一 需要重寫hashcode和equals方法
hashcode()與equals()方法。
先比較hashCode
如果hashCode不同 添加到集合
如果hahhCode相同 繼續比較equlas
如果內容相同 則不添加
如果內容不同 則添加
hashcode重寫以後可以將元素內的地址值進行比較,如果地址值相同,那麼就直接pass掉,不去進行equals的判斷,元素的地址值不同,那麼這兩個元素可能不同,如果元素的地址值相同,那麼這兩個元素的內容肯定是相同的.所以使用hashset進行判斷的時候可以省去很多判斷所花費的時間,提高了運行時候的效率性,
因爲集合內元素的地址值是java爲每個元素賦予的唯一的一個,具有唯一性,那麼我們是不是可以說在set接口內,如果相同了,那麼就代表兩個元素是相同的,那爲什麼有說兩個地址值不同,元素可能不同呢?難道有相同的情況嗎?
public class Demo02_HashSet {
public staticvoid main(String[] args) {
HashSet<String>set = newHashSet<String>();
set.add("abc");
set.add("bcd");
set.add("abc");
set.add("農豐");
set.add("兒女");
System.out.println(set);
Strings = "abc";
System.out.println(s.hashCode());
System.out.println("農豐".hashCode());
System.out.println("兒女".hashCode());
}
}
有興趣的小夥伴可以試一試農豐和女兒這兩個元素的地址值是不是相同,我測試的結果是,他們的地址值是相同的,內容卻不同.因爲hashcode的地址值是通過固定算法算出來的,所以通過計算的出來農豐和女兒的地址值是相同的,爲了避免這種例外情況的發生,我們需要在這種特殊情況下使用equals進行再次判斷.
在調用hashcode和equals方法已經被重寫過了,在源碼中的重寫方法是這樣的
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 booleanequals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObjectinstanceof String) {
String anotherString = (String) anObject;
int n= value.length;
if (n== anotherString.value.length) {
charv1[] = value;
charv2[] = anotherString.value;
inti = 0;
while(n-- != 0) {
if(v1[i] !=v2[i])
return false;
i++;
}
returntrue;
}
}
return false;
}
下面通過一個綜合性的例題展示給大家,set接口下,的hashset的用法.
雙色球規則:雙色球每注投注號碼由6個紅色球號碼和1個藍色球號碼組成。紅色球號碼從1—33中選擇;藍色球號碼從1—16中選擇.請隨機生成一注雙色球號碼
publicclassTest01 {
publicstaticvoidmain(String[] args) {
//1.創建Random隨機數對象
Randomran = newRandom();
//2.創建HashSet用於保存不重複的紅球
HashSet<Integer>hs = newHashSet<>();
//3.循環判斷紅球數量是否小於6個
while(hs.size() < 6) {
// 4.球數量小於6個就產生一個紅球.添加到HashSet中
intnum= ran.nextInt(33) + 1;
hs.add(num);
}
//5.在生成一個紅球
intblueBall= ran.nextInt(16) + 1;
//6.打印中獎號碼
System.out.println("雙色球中獎號碼:");
System.out.print("紅球是: ");
for(Integer redBall : hs){
System.out.print(redBall+ " ");
}
System.out.println();
System.out.println("藍球是: " + blueBall);
}
}
我已經反覆練習過幾次這幾個代碼,感覺對hashset的使用會有一些從底層到實際使用的很好認知過程.