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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 唐巍 黑马帝   /  2012-3-21 02:38  /  2736 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

HashSet集合在判断集合元素是否存在时,为什么需要通过元素的两个方法hashCode和equals来实现?能不能只用其中一种方法?还有,下面这个hashCode方法:
                public int hashCode()
        {
            return name.hashCode()+age*46;//这里age*46是什么意思?
        }

3 个回复

倒序浏览
本帖最后由 ♂诸侯♂ 于 2012-3-21 03:12 编辑

hashSet里边会有一个默认的比较方法,判断hashSet中元素是否相同  通过hashCode 和equals方法来比较
先比较元素hashCode值是不是相同  如果相同  才会判断equals方法是否为true  是的话两元素就相同  不是的话就是不同
是为了保证元素唯一性的。

这个里边  你首先要了解的是  set集合中元素是不可以重复的   如果元素重复了  那么后边的将不会进入集合中 。


这个题中它返回的是name.hashCode()+age*46  简单说就是一个数  如果直接是name.hashCode()+age这个的话   那么很有可能会出现这样一种情况 name.hashCode()是30 age是10   那么他们的和是40   而这时另一个元素中  name.hashCode()是10  age是30  那么另一元素的和也是40   这样hashCode方法就判断两元素相同 回去用equals方法比较   效率较低  所以可以让age*46  这样他们的和算的时候相同的几率就比较小   很少会用到equals方法去比较了  这样效率较高  乘号后边可以是任意的一个数  关键不在这个数是几的问题  而是说乘以一个数  很大可能会让他们通过hashCode方法直接就比较出来是不是相同
  1. package Test;

  2. import java.util.HashSet;

  3. class Person
  4. {
  5.         private String name;
  6.         private int age;
  7.         Person(String name,int age)
  8.         {
  9.                 this.name = name;
  10.                 this.age = age;
  11.         }
  12.        
  13.         public int hashCode()
  14.         {
  15.                 System.out.println(this.name+"....hashCode");
  16.                 return name.hashCode()+age*37;
  17.         }

  18.         public boolean equals(Object obj)
  19.         {

  20.                 if(!(obj instanceof Person))
  21.                         return false;

  22.                 Person p = (Person)obj;
  23.                 System.out.println(this.name+"...equals.."+p.name);

  24.                 return this.name.equals(p.name) && this.age == p.age;
  25.         }

  26.        
  27.         public String getName()
  28.         {
  29.                 return name;
  30.         }
  31.         public int getAge()
  32.         {
  33.                 return age;
  34.         }
  35. }
复制代码
回复 使用道具 举报
HashSet是Set集合的子类,而在Set体系中必须保证元素是唯一的,这在HashSet集合中就是通过元素的两个方法hashCode和equals来实现的。
此时判断元素的存在性只是间接的,并不是说元素的这两种方法就是为了判断存在性的
而至于name.hashCode()+age*46中*46只是为了减小由于偶然姓名、年龄的选取导致的该hash值相同出现错误判断的机率
回复 使用道具 举报
往HashSet集合里面存入元素的时候,默认的会首先调用hashCode()方法,去判断所存元素的hash值和集合里面元素的hash值是否相同,若果不相同就把元素存入到集合中,如果相同了就会调用equals方法再进行比较。打个比方说
Student s1 = new Student("zhangsan",25);
Student s2 = new Student("zhangsan",25);
创建了两个学生对象,我们存入的意思是如果姓名和年龄都相同,就是同一个,第二个不往里面存,如果不覆写hashCode()这个方法这两个学生对象往HashSet集合里面存的话,肯定都会存进去的,因为两个学生对象的地址值都不一样。可以看下面的代码
  1. import java.util.*;
  2. public class HashSetDemo {
  3.         public static void main(String[] args){
  4.                 HashSet hs = new HashSet();
  5.                 hs.add(new Student("zhangsan",26));
  6.                 hs.add(new Student("lisi",25));
  7.                 hs.add(new Student("wangwu",21));
  8.                 hs.add(new Student("wangwu",21));
  9.                 hs.add(new Student("zhangsan",26));
  10.                 Iterator it = hs.iterator();
  11.                 while(it.hasNext()){
  12.                         Student s = (Student)it.next();
  13.                         System.out.println(s.getName()+".."+s.getAge());
  14.                 }                       
  15.         }
  16. }
  17. class Student{
  18.         private String name;
  19.         private int age;
  20.         Student(String name,int age){
  21.                 this.name = name;
  22.                 this.age = age;
  23.                
  24.         }
  25.         public int hashCode(){
  26.                 System.out.println("hashCode"+"..."+this.name);
  27.                 return name.hashCode()+age*21;
  28.                
  29.         }
  30.         public boolean equals(Object obj){
  31.                 if(!(obj instanceof Student))
  32.                         return false;
  33.                 Student s = (Student)obj;
  34.                 System.out.println(this.name+".."+s.name);
  35.                 System.out.println(this.age+".."+s.age);
  36.                 return this.name.equals(s.name)&&this.age==s.age;
  37.                        
  38.         }
  39.         public String getName() {
  40.                 return name;
  41.         }
  42.         public void setName(String name) {
  43.                 this.name = name;
  44.         }
  45.         public int getAge() {
  46.                 return age;
  47.         }
  48.         public void setAge(int age) {
  49.                 this.age = age;
  50.         }
  51. }
复制代码
如果没有覆写hashCode();只覆写equals()方法的话,直接判断完地址值不相同就会把对象都存进去,根本不会再去调用equals()方法。
至于你说的return name.hashCode()+age*46;这里age*46是为了提高效率,使其尽量在hashCode()方法里判断完是否为同一个元素。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马