标签:
平时使用map时都是用JAVA原生的类型,所以很少关注到hashcode()和equals()的方法的内部实现。近期实现一个小工具,涉及到自己写的类的查找比对,又再次重温了相关的知识。
上简单示例代码,比对自己覆写和不覆写的差异
不覆写hashcode()和equals():
1 import java.util.HashMap; 2 import java.util.Map; 3 4 public class HashCode_Equals { 5 6 public int a; 7 public int b; 8 9 public static void main(String[] args) { 10 11 Map<HashCode_Equals, String> map = new HashMap<HashCode_Equals, String>(); 12 13 HashCode_Equals obj1 = new HashCode_Equals(); 14 obj1.a = 1; 15 obj1.b = 1; 16 map.put(obj1, "test"); 17 18 HashCode_Equals obj2 = new HashCode_Equals(); 19 obj2.a = 1; 20 obj2.b = 1; 21 22 System.out.println("obj1.equals(obj2)=" + obj1.equals(obj2)); 23 System.out.println("map.get(obj2)=" + map.get(obj2)); 24 } 25 }
执行结果:
obj1.equals(obj2)=false
map.get(obj2)=null
仅覆写equals()方法
1 import java.util.HashMap; 2 import java.util.Map; 3 4 public class HashCode_Equals { 5 6 public int a; 7 public int b; 8 9 @Override 10 public boolean equals(Object obj) { 11 if (this == obj) 12 return true; 13 if (obj == null) 14 return false; 15 if (getClass() != obj.getClass()) 16 return false; 17 HashCode_Equals other = (HashCode_Equals) obj; 18 if (a != other.a) 19 return false; 20 if (b != other.b) 21 return false; 22 return true; 23 } 24 25 public static void main(String[] args) { 26 27 Map<HashCode_Equals, String> map = new HashMap<HashCode_Equals, String>(); 28 29 HashCode_Equals obj1 = new HashCode_Equals(); 30 obj1.a = 1; 31 obj1.b = 1; 32 map.put(obj1, "test"); 33 34 HashCode_Equals obj2 = new HashCode_Equals(); 35 obj2.a = 1; 36 obj2.b = 1; 37 38 System.out.println("obj1.equals(obj2)=" + obj1.equals(obj2)); 39 System.out.println("map.get(obj2)=" + map.get(obj2)); 40 } 41 42 }
执行结果:
obj1.equals(obj2)=true
map.get(obj2)=null
同时覆写hashcode()和equals()(借用eclipse集成的功能自动生成)
1 import java.util.HashMap; 2 import java.util.Map; 3 4 public class HashCode_Equals { 5 6 public int a; 7 public int b; 8 9 @Override 10 public int hashCode() { 11 final int prime = 31; 12 int result = 1; 13 result = prime * result + a; 14 result = prime * result + b; 15 return result; 16 } 17 18 @Override 19 public boolean equals(Object obj) { 20 if (this == obj) 21 return true; 22 if (obj == null) 23 return false; 24 if (getClass() != obj.getClass()) 25 return false; 26 HashCode_Equals other = (HashCode_Equals) obj; 27 if (a != other.a) 28 return false; 29 if (b != other.b) 30 return false; 31 return true; 32 } 33 34 public static void main(String[] args) { 35 36 Map<HashCode_Equals, String> map = new HashMap<HashCode_Equals, String>(); 37 38 HashCode_Equals obj1 = new HashCode_Equals(); 39 obj1.a = 1; 40 obj1.b = 1; 41 map.put(obj1, "test"); 42 43 HashCode_Equals obj2 = new HashCode_Equals(); 44 obj2.a = 1; 45 obj2.b = 1; 46 47 System.out.println("obj1.equals(obj2)=" + obj1.equals(obj2)); 48 System.out.println("map.get(obj2)=" + map.get(obj2)); 49 } 50 51 }
执行结果:
obj1.equals(obj2)=true
map.get(obj2)=test
关于equals()方法不再多余介绍,重点篇幅是关于hashcode()的如何更好实现
《effective java》第9条:覆盖equals时总要覆盖hashcode
规范要求:相等的对象必须有相同的散列码。否则从map中当作key值得到的散列码是不同的,从而取到的value结果是不同的,上述的例子就是一个很好的证明
在不覆写的情况下,hashcode方法是JAVA默认生成的。从代码执行结果看obj1.equals(obj2)为true时,仍然hashcode不同,也就说JAVA默认的是不符合要求的,要求我们必须覆写。
关于hashcode,如果方法写的简单会造成hashcode的不断冲突,这样每个对象被映射到同一个散列桶中,使得散列表退化为链表。使得本应线性时间运行的程序变成了平方级在运行。
所以effecive java同时给了实现的参考
[JAVA 基础] hashcode() & equals()
标签:
原文地址:http://www.cnblogs.com/clarino/p/5448358.html