java 重写Object中的hashCode方法-----转载

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 重写Object中的hashCode方法-----转载相关的知识,希望对你有一定的参考价值。

  1  hashCode()用于返回调用该方法的对象的散列码值,此方法将返回整数形式的散列码值。
  2         在object类中,hashcode()方法是本地方法,返回的是对象的地址值,而object类中的equals()方法比较的也是两个对象的地址 值,如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了。一旦一个类重写equals()方法,通常也会重写 hashCode()方法。
  3 
  4        下面是重写hashCode()方法的约定的内容,来自Object规范[JavaSE6]:
  5 
  6         (1)、在应用程序的执行期间,只要对象的equals方法的比较操作所用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法都必须始终如一地返回同一个整数。在同一个应用程序的多次执行过程中,每次执行所返回的整数可以不一直。
  7 
  8         (2)、如果两个对象根据equals(Object)方法比较是相等的,那么调用这两个对象中任意一个对象的hashCode方法都必须产生同样的整数结果。
  9 
 10         (3)、如果两个对象根据equals(Object)方法比较是不相等的,那么调用这两个对象中任意一个对象的hashCode方法,则不一定要产生不同的整数结果。但是程序员应该知道,给不相等的对象产生截然不同的整数结果,有可能提高散列表的性能。
 11 
 12         总之只有一个目的:hashCode方法要为"不相等的对象产生不相等的散列吗"。下面我给出一个反例的代码。
 13 
 14 [java] view plain copy
 15 import java.util.HashSet;    
 16     
 17 public class User {    
 18     //用户名称    
 19     private String userName;    
 20     //用户密码    
 21     private String password;    
 22         
 23     public User(String userName, String password){    
 24         this.userName = userName;    
 25         this.password = password;    
 26     }    
 27         
 28     /**  
 29      * 覆盖equals方法  
 30      */    
 31     public boolean equals(Object obj){    
 32         if(obj == null){    
 33             return false;    
 34         }    
 35         //如果是同一个对象返回true,反之返回false    
 36         if(this == obj){    
 37             return true;    
 38         }    
 39         //判断是否类型相同    
 40         if(this.getClass() != obj.getClass()){    
 41             return false;    
 42         }    
 43         User user = (User)obj;    
 44         return userName.equals(user.userName) && password.equals(user.password);    
 45     }    
 46         
 47     public String toString(){    
 48         //System.out.println(userName.hashCode() + "      oooo");    
 49         return userName + ":" + password;    
 50     }    
 51         
 52     public static void main(String[] args) {    
 53         HashSet<User> set = new HashSet<User>();    
 54         User user01 = new User("xiaom", "1");    
 55         User user02 = new User("xiaom", "1");    
 56         User user03 = new User("xiaoh", "2");    
 57         User user04 = new User("xiaoj", "3");    
 58         set.add(user01);    
 59         set.add(user02);    
 60         set.add(user03);    
 61         set.add(user04);    
 62             
 63         System.out.println("对象的内容" + "\t\t" + "对象的散列码");    
 64         for(User user : set){    
 65             System.out.println(user.toString() + "\t\t" + user.hashCode());    
 66         }    
 67     }    
 68        输出的结果:
 69 
 70 [java] view plain copy
 71 对象的内容   对象的散列码    
 72 xiaoj:3     17510567    
 73 xiaom:1     6413875    
 74 xiaoh:2     827574    
 75 xiaom:1     21174459    
 76 
 77         这时候,我们可能期望只打印三个对象的值。由于我们重写了equals方法,所以user01对象和user02的对象是相等的。那么在hashSet集合中就应该只有三个元素。这是为什么呢?
 78 
 79        Java 中的集合类有两类:一类是List,一类是Set。前者允许集合内的元素可 以重复,后者则不允许集合中的元素可以重复。那么Java是如何判断集合中的元素是否重复呢?是通过对象中的equals()方法进行比较。但是,如果每 增加一个元素,都要进行一次equals比较。那么当集合中有很多元素时,就要进行很多次比较。也就是说,如果集合中有10000个元素,就得调用 10000次equals。这很明显降低了效率。于是,Java就采用了哈希表的原理,将数据依据指定的算法映射到一个地址上。这样一来,当集合要添加一 个元素时,只要调用该对象的hashCode方法,就可以找到指定的物理地址。如果该地址上没有元素,那么就将元素放在该地址上,不用再进行其他任何比较 了。如果该地址上有元素,那就调用equals方法进行比较,如果相同,则不需要添加改元素;如果不相同,就散列到其他地址。这样一来,实际调用 equals方法的次数就大大地减少了。
 80 
 81        我们再回过头看看刚刚的小例子。会出现那种错误,是因为我们没有重写hashCode方法。HashSet调用的是Object中的hashCode方法,而Object中的hashCode方法返回的是对象的地址值,所以HashSet认为user01对象与user02对象是不相等的,才在hashSet集合中出现4个对象。现在我们就来重写一下hashCode方法,看看效果如何,代码如下:
 82 
 83 [java] view plain copy
 84 import java.util.HashSet;    
 85     
 86 public class User {    
 87     //用户名称    
 88     private String userName;    
 89     //用户密码    
 90     private String password;    
 91         
 92     public User(String userName, String password){    
 93         this.userName = userName;    
 94         this.password = password;    
 95     }    
 96         
 97     /**  
 98      * 覆盖equals方法  
 99      */    
100     public boolean equals(Object obj){    
101         if(obj == null){    
102             return false;    
103         }    
104         //如果是同一个对象返回true,反之返回false    
105         if(this == obj){    
106             return true;    
107         }    
108         //判断是否类型相同    
109         if(this.getClass() != obj.getClass()){    
110             return false;    
111         }    
112         User user = (User)obj;    
113         return userName.equals(user.userName) && password.equals(user.password);    
114     }    
115         
116     /**  
117      * 重写toString  
118      */    
119     public String toString(){    
120         return userName + ":" + password;    
121     }    
122         
123     /**  
124      * 重写hashCode  
125      */    
126     public int hashCode(){    
127         int result = 17;    
128         result = 31 * result + userName.hashCode();    
129         result = 31 * result + password.hashCode();    
130         return result;    
131     }    
132     
133     public static void main(String[] args) {    
134         HashSet<User> set = new HashSet<User>();    
135         User user01 = new User("xiaom", "1");    
136         User user02 = new User("xiaom", "1");    
137         User user03 = new User("xiaoh", "2");    
138         User user04 = new User("xiaoj", "3");    
139             
140         set.add(user01);    
141         set.add(user02);    
142         set.add(user03);    
143         set.add(user04);    
144         System.out.println("对象的内容" + "\t\t" + "对象的散列码");    
145         for(User user : set){    
146             System.out.println(user.toString() + "\t\t" + user.hashCode());    
147         }    
148     }    
149 }     
150        输出的结果:
151 
152 
153 [java] view plain copy
154 对象的内容     对象的散列码    
155 xiaom:1        -759483308    
156 xiaoh:2        -759483462    
157 xiaoj:3        -759483399   
158          执行结果正确,收工。
159 
160 161 0

 

以上是关于java 重写Object中的hashCode方法-----转载的主要内容,如果未能解决你的问题,请参考以下文章

在java中,关于equals(),和hashCode()的重写问题。

重写java类的equals()和hashCode方法

Java 为什么重写equals的时候必须重写hashCode

Java重写hashCode()和equals()方法

java中重写Object类的equals方法为啥要重写hashcode方法?不重写可以吗?

java中重写Object类的equals方法为啥要重写hashcode方法?不重写可以吗?