在集合框架中,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的使用会有一些从底层到实际使用的很好认知过程.