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