HashSet剖析

HashSet底层是HashMap实现,不保证顺序恒久不变。优点是利用哈希表提高查询效率,缺点是元素不能重复。

一 哈希表如何提高查询效率

Object类中含有hashCode和equals方法,故String类重写了两种方法。其中重写的hashCode方法就相当于下图的hash函数,给对象映射到一个hash值,放到哈希表里,用于在哈希表存放位置的比较。重写的equals方法用于进一步判断对象是否相同,若地址相同,比如“bac和abc”按照String的hashCode方法有相同的地址,但是他们是不同的。故还需要通过equals方法判断对象内容是否相同。

String的hashCode源码:引用

“`
public int hashCode() {
int h = hash;
//如果hash值没有被计算过,并且字符串不为空,则进行hashCode计算
if (h == 0 && value.length > 0) {
char val[] = value;

    //每个字符的hash值累加和为最终结果  
    for (int i = 0; i < value.length; i++) {  
        h = 31 * h + val[i];  
    }  
    hash = h;  
}  
return h;  

}
“`这里写图片描述

二 哈希表如何判断元素是否相同:

1> 哈希值是否相同 :判断的其实是对象的hashCode()方法是否相同(看对象是否在哈希表的同一个位置)
2>内容是否相同:用equals方法判断对象是否相同。
规则:若hash值不同,不必判断对象内容,返回false;若hash值相同,有必要判断对象内容,若在相同,返回true,否则false。

三 往hashSet中存放自定义对象

往hashSet中存放Car这个对象,其有名字和车轮数两个属性。由于hashSet不允许有重复的元素,下面的代码说明为啥添加两次“BWM,4”仍会输出结果。

public class Car{  
    String name;  
    int viechle;  

    public Car(String name,int viechle){  

        this.name=name;  
        this.viechle=viechle;  
    }  
    public String getNameViechle() {  
        return name+" "+viechle;//  
    }  

    public void setNameViechle(String name,int viechle) {  
        this.name = name;  
        this.viechle=viechle;  
    }  

}  
public class HashSetDemo {
        public static void main(String[] args) {  
        // TODO Auto-generated method stub  
        Set <Car>hs=new HashSet<Car>();  
        hs.add(new Car("BWM",4));  
        hs.add(new Car("BWM",4));  
        Iterator<Car> it=hs.iterator();  
        while(it.hasNext()){  
            Car car=it.next();  
            System.out.println(car.getNameViechle());  
        }  
    }  
}  

输出:BWM 4 BWM 4

由于HashSet不允许元素重复,故需要判断元素是否相同,我们都知道ArrayList中判断元素是否相同用equals方法;但hashSet底层由哈希表实现,数据结构决定性质,故需要用hash表判断元素是否相同的方法,即需要hashCode和equals两个方法,对于hashSet,先通过hashCode判断元素在哈希表中的位置是否相同,在通过equals方法判断元素内容是否相同。(默认说明先调用hashCode方法,而且两个方法必须一起重写)故需要在上述代码Car类中添加重写的两个方法。

public class Car{  
    String name;  
    int viechle;  

    public Car(String name,int viechle){  

        this.name=name;  
        this.viechle=viechle;  
    }  
    public String getNameViechle() {  
        return name+" "+viechle;  
    }  

    public void setNameViechle(String name,int viechle) {  
        this.name = name;  
        this.viechle=viechle;  
    }  
    @Override  
    public int hashCode() {  
        return 31*name.hashCode()+viechle;  
    }  
    @Override  
    public boolean equals(Object obj) {  
        if(this==obj)return true;  
        if(!(obj instanceof Car)) throw new ClassCastException("类型转换异常");  
        Car car=(Car)obj;  
        return this.name.equals(car.name)&&this.viechle==car.viechle;  
    }  

}
public class HashSetDemo {  

        public static void main(String[] args) {  
        // TODO Auto-generated method stub  
        Set <Car>hs=new HashSet<Car>();  
        hs.add(new Car("BWM",4));  
        hs.add(new Car("BWM",4));  
        Iterator<Car> it=hs.iterator();  
        while(it.hasNext()){  
            Car car=it.next();  
            System.out.println(car.getNameViechle());  
        }  
    }  
}  

输出:BWM,4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值