黑马程序员技术交流社区

标题: 关于equals 和 hashcode 的问题 [打印本页]

作者: 梦想注定是孤独    时间: 2014-3-2 12:48
标题: 关于equals 和 hashcode 的问题
在HashSet集合中 ,Person去重是依据复写equals和hashcode这个两个方法  具体为啥依据这两个方法还是有点不清!!!
只知道如果不复写的话HashSet就看的是Person这个对象的地址值!!!




迷迷糊糊的根据毕老师老师讲的写了一段代码 。可是还是去不了重  大家帮忙看看


  1. import java.util.*;
  2. class  HashSetDemo
  3. {
  4.         public static void main(String[] args)
  5.         {
  6.         HashSet<Person> hs = new HashSet<Person>();
  7.         hs.add(new Person("zhangsan",21));
  8.         hs.add(new Person("lisi",20));
  9.         hs.add(new Person("lisi",20));
  10.         hs.add(new Person("wangwu",24));
  11.         hs.add(new Person("zhaoliu",23));
  12.         hs.add(new Person("zhaoliu",23));
  13.        
  14.         Iterator <Person>it = hs.iterator();
  15.         while(it.hasNext())
  16.         {
  17.          Person p = it.next();
  18.          System.out.println(p);
  19.         }

  20.         }
  21. }

  22. class Person
  23. {
  24.         private String name;
  25.         private int age;
  26.         Person(String name,int age){
  27.         this.name = name;
  28.         this.age = age;
  29.         }
  30.         public String toString()
  31.         {
  32.         return name+"..."+age;
  33.         }

  34.         public String getName(){return name;}
  35.         public int getAge(){return age;}
  36.         public int hashcode()
  37.         {
  38.         final int x = 5;
  39.         return this.name.hashCode() + this.age * x;
  40.         }

  41.         public boolean equals(Object obj)
  42.         {
  43.           if (this == obj)
  44.                   return true;
  45.           if (obj instanceof Person)
  46.                 { Person p = (Person)obj;
  47.                   return this.name.equals(p.name) && this.age == p.age;}
  48.           return false;

  49.           
  50.           
  51.         }
  52. }
复制代码




作者: 戚兴海    时间: 2014-3-2 13:07
HashSet的底层是哈希表结构,内部元素的存储的也是按照哈希表的方式存储的,所以你存入一个Person对象之后,集合中存储的是与之对应的哈希值。
那么什么是哈希值,哈希值就是对象在堆内存中存储的位置,就是一个数值,它有自己的计算方式。
如果不重写HashCode方法的话,按照默认的哈希值计算方法(从Object中继承来的),所有单独创建出来的Person对象的哈希值都是不同的,因为是不同的对象,即使姓名年龄一样的也被判定是不同的对象。

HashSet中判断元素是否重复的依据,首先就要判断元素对象的哈希值是否一样,如果哈希值不一样的话,就会接受并加入集合中。那么我们就需要重写hashCode方法,定义我们自己的计算方式,让姓名年龄一样的Person对象拥有一样的哈希值。如果元素的哈希值相同,接下来才会调用equals方法去判断。

结论就是:在和哈希表相关的集合中,重写equals方法的同时要重写hashCode方法!
作者: 梦想注定是孤独    时间: 2014-3-2 13:25
戚兴海 发表于 2014-3-2 13:07
HashSet的底层是哈希表结构,内部元素的存储的也是按照哈希表的方式存储的,所以你存入一个Person对象之后 ...

哦,谢谢你。但是我这段代码的Person已经复写了hashCode  按说HashSet在比较的时候就能把重复元素去了  可是为什么还是去不了重复元素呢?
作者: volvoxc    时间: 2014-3-2 13:26
我看了你的代码,应该是这个问题,你并没有重写hashCode方法,你的代码中写的的hashcode。所以,每个对象的哈希值都不相同,也就不会再调用equals方法了,直接就判断两个对象不同了。
作者: yunzhongzhuhuo    时间: 2014-3-2 13:29
你看看这个person类,你写的有点问题
  1. class Person{
  2.        
  3.         private String name;
  4.         private int age;
  5.         public Person(String name, int age) {
  6.                 this.name = name;
  7.                 this.age = age;
  8.         }
  9.         public String getName() {
  10.                 return name;
  11.         }
  12.         public void setName(String name) {
  13.                 this.name = name;
  14.         }
  15.         public int getAge() {
  16.                 return age;
  17.         }
  18.         public void setAge(int age) {
  19.                 this.age = age;
  20.         }
  21.         @Override
  22.         public boolean equals(Object arg0) {
  23.                 // TODO Auto-generated method stub
  24.                 if(!(arg0 instanceof Person))
  25.                         return false;
  26.                 Person p=(Person)arg0;
  27.                 return this.name.equals(p.getName())&&this.age==p.getAge();
  28.         }
  29.         @Override
  30.         public int hashCode() {
  31.                 // TODO Auto-generated method stub
  32.                 return this.name.hashCode()+this.age*12;
  33.         }
  34.        
  35.        
  36. }
复制代码




作者: 梦想注定是孤独    时间: 2014-3-2 13:38
volvoxc 发表于 2014-3-2 13:26
我看了你的代码,应该是这个问题,你并没有重写hashCode方法,你的代码中写的的hashcode。所以,每个对象的 ...

谢谢!刚改了 。OK了  谢谢
作者: 梦想注定是孤独    时间: 2014-3-2 13:39
yunzhongzhuhuo 发表于 2014-3-2 13:29
你看看这个person类,你写的有点问题

谢谢!@




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