A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 王广彬 中级黑马   /  2012-8-12 22:24  /  1969 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

package cn.set;
importjava.util.HashSet;
importjava.util.Iterator;

// 往hashSet集合中存入自定义对象.如果姓名和年龄相同的为同一个人,删除
class Person{
    private String name;
    private int age;
    public Person(String name,int age){
        this.setName(name);
        this.setAge(age);
    }
    public int hashCode(){          //hashCode()有什么用?是在什么时候调用?
        return name.hashCode()+age;  //返回name.hashCode()+age;又是什么意思啊?
    }                                  //看不明白能不能给解释一下?
    public boolean equals(Object obj){          //判断对象是否相同
        if(!(obj instanceof Person)){
            return false;
        }
        Person p=(Person)obj;

        //System.out.println(this.name+".........."+p.name);

        returnthis.name.equals(p.name)&&this.age==p.age;
    }
    public void setName(String name){
        this.name=name;
    }
    public void setAge(int age){
        this.age=age;
    }
    public String getName(){
        returnname;
    }
    public int getAge(){
        return age;
    }
}
public classHashSetDemo1 {
    public static void main(String[] args){
        HashSet hset=new HashSet();
        hset.add(new Person("黄晓明",21));
        hset.add(new Person("周星驰",23));
        hset.add(new Person("陈小春",22));
        hset.add(new Person("周星驰",23));
        hset=deleteSameElement(hset);         //把去除重复元素后的集合赋给hset
        for(Iteratorit=hset.iterator();it.hasNext();){
            Person p=(Person)it.next();
            sop(p.getName()+"==="+p.getAge());
        }
    }
    public static HashSet deleteSameElement(HashSethash){
        HashSet haha=new HashSet();
        for(Iteratorit=hash.iterator();it.hasNext();){
            Object obj=it.next();
            if(!(haha.contains(obj))){
                haha.add(obj);
            }
        }
        return haha;
    }
    public static void sop(Object obj){
        System.out.println(obj);
    }
}
各位大侠,今天看视频这段代码有点费解,就是红色字体那段,hashCode是怎么用的?程序在运行时什么时候调用它啊?能不能给解释一下,看不懂,谢谢!

评分

参与人数 1技术分 +1 收起 理由
张_涛 + 1 赞一个!

查看全部评分

4 个回复

正序浏览
王广彬 发表于 2012-8-12 23:14
哦,那么hashCode方法是在什么时候调用的?主方法中没看到被调用啊?

hashCode方法是在你往set集合中add对象时自动调用的,set集合的元素为什么不可以重复,就是因为在add对象时进行了相关的比较操作(调用hashCode和equals方法)~
回复 使用道具 举报
        首先我要说下,这里很多人都存在疑惑,不知道这样做是为什么,思路也很难理清,希望楼主能够实实在在的理解了其中的道理;
        hashSet保证元素唯一性的原理:判断元素的hashCode值是否相同,如果相同,还会继续判断元素的equals方法,是否为true;
        因为HashSet集合是根据对象的地址值来存放对象的,而对象的地址值是根据哈希算法得来的,默认情况下(就是不覆写Object的hashCode方法)是调用windows底层的一个哈希算法。
        Object的原始的hashCode()方法中是将对象的内存地址值作为实例的哈希值,因此在使用Set的时候就一定要覆写hashCode()方法。
        为什么要覆写呢?原因是Set在add一个新对象的时候并不是将这个新对象与Set内的对象逐一通过equals()进行比较,而是先比较新对象与Set内的对象的哈希值以区分新对象是否重复,因为Set中不允许存在重复元素。比如你的代码中new了四个Persont类的新对象:
        hset.add(new Person("黄晓明",21));
        hset.add(new Person("周星驰",23));
        hset.add(new Person("陈小春",22));
        hset.add(new Person("周星驰",23));
          在添加第四个人的时候,你肯定希望这个人无法被添加,因为上面已经添加了相同的人;
如果你不覆写Person类的hashCode()方法,那么此时第四个人是可以被添加的,因为第四个人和第二个人的内存地址不同,所以要覆写hashCode()方法,生成Person类自己独有的哈希值,怎么覆写呢?这就应该根据你的判断条件来生成相应的哈希值。你的判断条件就是姓名相同、年龄也相同,那就是同一个人!

          那么这里为什么要返回:name.hashCode()+age;
          这里要说下,因为name是String类型,String类中也有hashCode方法,所以name.hashCode()返回的也是一个int类型,这个int类型的哈希值加上年龄不就生成每个对象独有的哈希值了么。你添加的姓名或年龄中只要有一样不相同,那name.hashCode()+age;返回的int类型的值肯定也不相同。

          再仔细想想,是不是有这样一种情况:如果有些人姓名不同,年龄也不同,但是经过 name.hashCode()+age 算下来之后,哈希值竟然相同!结果呢?还要继续调用equals方法进行内容比较,你说,本来就不是同一个人,还要再进一步去比较,多麻烦啊,效率自然也就不会高了,虽然这种情况少见,但也要预防,尽最大努力让每个对象的哈希值唯一!所以,毕老师视频中他就把age又乘了个整数,比如37:name.hashCode()+age*37;数学上有这样一个道理:在越大的范围内,两个数相同的概率就越小!这样的话把结果放大后,你看上面那种情况出现的概率是不是就要低很多了呀!

评分

参与人数 1技术分 +1 收起 理由
张_涛 + 1 赞一个!

查看全部评分

回复 使用道具 举报
哦,那么hashCode方法是在什么时候调用的?主方法中没看到被调用啊?
回复 使用道具 举报
Set集合判断元素重复的方法,hashCode和equals
equals里面定义了如何判断两个Set集合元素是否相等。
具体的说由于Set集合里的元素是不重复的,那当加入一个新元素就需要那这个元素与集合里的其他元素作比较,如果集合中已存在要加入的元素,也就是符合自己定义的equals里的判断方式,那就不会添加这个元素,以保证集合里的成员唯一。
hashCode的作用也是保证Set集合里成员唯一,而且是先判断hashCode的值是否相等,如果相等在判断equals是否相等,如果都相等,那说明集合中已经存在相同成员了。至于为什么 要写成  i  = 10 * i + age; 先要说说这句代码要做什么,就拿上面的1,2两个对象来说,i 就是那两个对象中jack对应的hash值,都是jack所以这两个是相同的,在加上age,都是20当然也相等了。但有一种特殊情况,假如有这样两个对象
              new Person("Jack", 20));
             new Person("Jahn",50));
这两个肯定不相等,但恰好jack对应的hash值是50,jahn的hash值是20。20+50=50+20,这样本来不应该相等的两个元素,却被判断为相等。所以年龄乘以随便一个数就可以避免这种情况发生。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马