黑马程序员技术交流社区

标题: HashMap中重写equals方法的疑问 [打印本页]

作者: 张权    时间: 2013-1-8 20:53
标题: HashMap中重写equals方法的疑问
本帖最后由 张向辉 于 2013-1-16 12:04 编辑

public boolean equals(Object obj) {
                              //问题,为什么要先重写hashCode()方法,后重写equals方法,equals这里为什么要比较引用,下面又比较引用的属性,而且这里比较引用后还直接返回,这样下面的属性不叫就不执行了,
                             //这段重写代码到底想表达什么?
                if(this==obj){
                        return true;
                }
               
                if(!(obj instanceof Person)){
                        return false;
                }
               
                //向下转型
                Person p = (Person)obj;
                return this.name.equals(p.name) && this.age == p.age;
        }

作者: Rancho_Gump    时间: 2013-1-8 21:07
本帖最后由 张向辉 于 2013-1-8 21:08 编辑

HashSet要保证元素唯一性,通过元素的两个方法,hashCode和equals来完成,所以要装入hashSet的元素必须有这两个方法。
HashSet首先通过hashCode方法判断,若不同,则视为两个元素不同,不再执行equals方法;
如果判断相同,则再执行equals方法判断,若equals方法返回false,则视为元素不同,若为true(即hashSet和equals都是true)则视为同一元素,不能存入hashset集合

毕老师的视频这点讲的很不错的,可以再仔细看下   希望对你有帮助   {:soso_e100:}
作者: 胡勇敏    时间: 2013-1-8 21:08
HashMap判断两个元素是否为同一元素时,依靠的是hashCode与equals方法。首先各个元素会先调用hashCode方法计算自己的hashCode值,当两个元素的hashCode不同时直接判断对象为不同对象,存入集合。而当两个对象的hashCode值相同时,则会进一步调用equals方法进行判断,如果equals返回真则为同一元素,不存入集合。而当equals返回假时则判定为不同元素,存入集合中的同一地址下。所以如果覆写hashCode方法,让不同的对象尽量返回各自不同hash值可以提高程序的效率。

作者: 肖志锋    时间: 2013-1-8 21:10
首先说为什么要重写hashCode方法,因为作为Map他的定义里面,键就必须是唯一的,说到这里我想你需要注意的一个细节是你重写这些方法的那个自定义类的对象是作为键的,你这里是Person,也就是这个类的对象在Map里面是作为键的存在,而不是值。如果Person是值的话,就是另外一回事了,代码会简单很多。
其次,如何实现那个键的唯一呢?你可以去看看原码,原码里面使用的是hashCode和equals两个方法,而且是只有当hashCode一样的时候才调用equals方法。这就回答了为什么的问题原因,就是java原码的逻辑顺序就是这样。你可以去看看原码。
第三,我再解释下你那个重写的equals方法的逻辑,首先你要明白这个方法是谁调用的,参数是什么?从Object继承下来的,你应该知道,他是对象自己的一个方法,用自己去跟参数对象比较,而参数是Object对象。一样则为真。
第一句,因为实体只能是引用去操作,所以我们先比较自身跟参数是不是指向同一个对象实体,也就是引用地址是不是一样,如果一样,则返回真。
如果不一样,则执行第2句,判断参数对象是不是跟调用者是同一个类,如果不是,则没必要比较了,假设参数是cat对象,则跟人比没意义,直接返回假。
真的话,则执行第3,4句,先强制类型转化参数,然后我们自定义比较名字,年龄一样的人是同一个人(这个比较的要求是自定义的,你可以改)。
这就是整个方法的逻辑,以及为什么要这么做。

作者: 张权    时间: 2013-1-8 21:14
张向辉 发表于 2013-1-8 21:07
HashSet要保证元素唯一性,通过元素的两个方法,hashCode和equals来完成,所以要装入hashSet的元素必须有这 ...

  我不懂为什么重写equals方法时,还要比较引用,而且引用比较了就已经返回true了,后面的比较属性就不会执行了,我想知道为什么判断引用也能判断是不是同一个元素,引用比较的不是内存地址值么?
作者: 张权    时间: 2013-1-8 21:28
肖志锋 发表于 2013-1-8 21:10
首先说为什么要重写hashCode方法,因为作为Map他的定义里面,键就必须是唯一的,说到这里我想你需要注意的 ...

我觉得第一句    if(this==obj){
                        return true;
                }
没什么用啊,因为两个new 出来的对象引用怎么可能相同呢?  
然后就是    Person p = (Person)obj;
                return this.name.equals(p.name) && this.age == p.age;
  之前比较过hashCode了,这里还比较对象的属性有什么用呢,之前复写hashCode方法已经证明它们的属性相同的
作者: 肖志锋    时间: 2013-1-8 21:51
。。你的hashCode,不管怎么写总有相同的可能 ,比如1+4=5,2+3=5,3+2=5,4+1=5,假如前面两个相加的数是属性什么,后面的5是hashCode ,那你认为这4组数据是同一个数吗?
而且,至于你说的对象什么的肯定不一样没有必要,我想说的是,你编程的思想需要深化了。举个例子吧 ,就像你从来不犯法,但你认为法律就没有用吗?因为你没办法保证每个人都守法,所以我们需要法律什么,放到这里,也就是你程序是写给别人用的,你不会用自己去比,你能保证比人不去比吗?如果比人要比呢?那你还从头到尾去算一遍,不是浪费系统资源吗?所以你要把最坏的结果打算好,而不是去期待不会出错。
作者: 张权    时间: 2013-1-8 23:18
肖志锋 发表于 2013-1-8 21:51
。。你的hashCode,不管怎么写总有相同的可能 ,比如1+4=5,2+3=5,3+2=5,4+1=5,假如前面两个相加的数是 ...

   嗯,明白了,谢谢!!!!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2