码迷,mamicode.com
首页 > 其他好文 > 详细

hashcode与equals的一些事

时间:2015-05-08 16:23:17      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:

  有时候一些东西不经意听见了,并不当回事,回头就忘了。人总是这么健忘!

  学习hebernate的时候,看到一句话,对于需要映射到数据库中的实体类需要满足几个要求,其中有一个是说对于重写了equals重写后要重写hashcode。相信这是一句老生常谈的话了,大家都不陌生。当时我也一扫而过。后来看到一个短片说怎样验证一个cookie有效性也提到了hash算法。于是就想验证一下之前的两个重写。

  当时随手就写了一段代码(没有用快捷键),如下:

 1 public class hash {
 2     public static void main(String[] args) {
 3     
 4         HashSet<Student> hs = new HashSet<Student>();
 5         Student stu1 = new Student("zhang");
 6         Student stu2 = new Student("zhang");
 7         
 8         hs.add(stu1);
 9         hs.add(stu2);
10         System.out.println(hs.size());
11     }
12 }
13 
14 class Student {
15     String name;
16 
17     Student( String name) {
18         this.name = name;
19     }
20     
21 //    @Override
22 //    public int hashCode() {
23 //        // TODO Auto-generated method stub
24 //        final int INDEX = 12345;
25 //        return name.hashCode()*INDEX;
26 //    }假若不覆盖hashcode方法会怎样啦!将会发现两个对象stu1和stu2我们期望是同一个,不用存进来了,但是在hash值这一关就没有过,new对象时默认以对象的内存地址映射hash值,也就是new了两个对象的hash值是不同的,
27 
28     //因此我们需要覆盖hashcode(),让它按我们的期望来返回hash值
29     
30     public int hashcode() {
31         
32         final int INDEX = 12345;
33         return name.hashCode()*INDEX;
34     }
35     
36     
37     public boolean equals(Student stu ) {
38         
39         if(this.name.equals(stu.name)){
40             return true;
41         }
42         return false;
43     }
44 }

  我期望是结果是set中只插入一个,但结果总是两个,搞得我都有点怀疑set插入的判断过程了,难道不是像记忆中的那样首先判断hash值,如果相等就判断equals,若equals相等就是说明是同一个,就不插入吗!郁闷了半天搞得。后来我说打印一下hash值看一下啦,结果吓我一大跳,怎么有两个.hashcode()方法,难道是我眼花吗,再仔细一看,打自己耳光的心都有,怎么可以将hashCode()写成hashcode(),赶紧改过来,但还是不对,问题又在哪里啦,这不是坑吗,短短的几行代码,为什么就是不能按我的想法来啦,郁闷。一共就两个方法,那在看看是不是equals啦,好吧,懒得自己写了,还是用快捷键了,一个alt+shift+s,覆盖equals看看,结果又让我不爽了,我的刚才的那个equals怎么就是Student参数啦,好吧,对自己无语了(说到这里就顺带说一下overload和override,前者是在同一个类中根据参数的不同重载,后面的是子类覆盖父类的方法,除了方法体里的东西不一样外,其余的都一样)。赶快修改过来,再运行,出现了自己想要的结果。

技术分享
 1 public class hash {
 2     public static void main(String[] args) {
 3     
 4         HashSet<Student> hs = new HashSet<Student>();
 5         Student stu1 = new Student("zhang");
 6         Student stu2 = new Student("zhang");
 7         
 8         hs.add(stu1);
 9         hs.add(stu2);
10         System.out.println(hs.size());
11     }
12 }
13 
14 class Student {
15     String name;
16 
17     Student( String name) {
18         this.name = name;
19     }
20     
21 //    @Override
22 //    public int hashCode() {
23 //        // TODO Auto-generated method stub
24 //        final int INDEX = 12345;
25 //        return name.hashCode()*INDEX;
26 //    }假若不覆盖hashcode方法会怎样啦!将会发现两个对象stu1和stu2我们期望是同一个,不用存进来了,但是在hash值这一关就没有过,new对象时默认以对象的内存地址映射hash值,也就是new了两个对象的hash值是不同的,
27 
28     //因此我们需要覆盖hashcode(),让它按我们的期望来返回hash值
29     @Override
30     public int hashCode() {
31         // TODO Auto-generated method stub
32         final int INDEX = 12345;
33         return name.hashCode()*INDEX;
34     }
35     
36     @Override
37     public boolean equals(Object obj) {
38         // TODO Auto-generated method stub
39         Student stu =(Student)obj;
40         if(this.name.equals(stu.name)){
41             return true;
42         }
43         return false;
44     }
45 }
View Code

  下面就说说如果我们不覆盖hashcode会是什么后果啦。按照我们的想法,stu1和stu2有同样的名字是同一个人,我们希望不要同时都放到set中,但是我们如果不覆盖hashcode,在new对象的时候就会将对象的内存地址映射成hash值,就会导致两个对象拥有不同的hash值,当然这不是我们想要的结果,所以我们需要覆盖上诉的两个方法次啊是完整的。

hashcode与equals的一些事

标签:

原文地址:http://www.cnblogs.com/Jc-zhu/p/4487988.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!