首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

浅谈equals跟hashcode

2012-12-26 
浅谈equals和hashcode关键字:?equals?,hashcode转自:http://www.sunxin.org/forum/thread/19720.html先谈e

浅谈equals和hashcode

关键字:?equals?,hashcode

转自:http://www.sunxin.org/forum/thread/19720.html

先谈equals。equals是Object类提供的方法之一,众所周知,每一个java类都继承自Object类,所以说每一个对象都有equals这个方法。而我们在用这个方法时却一般都重写这个方法,why?

Ok,先看一个Object类中equals()方法的源代码:

源码打印?
  1. public?boolean?equals(Object?obj)?{???
  2. ????return?(this?==?obj);???
  3. }??

?? ? ?从这个方法中可以看出,只有当一个实例等于它本身的时候,equals()才会返回true值。通俗地说,此时比较的是两个引用是否指向内存中的同一个对象,也可以称做是否实例相等。而我们在使用equals()来比较两个指向值对象的引用的时候,往往希望知道它们逻辑上是否相等,而不是它们是否指向同一个对象——这就是我们通常重写这个方法的原因。

?? ? ?在程序员之家论坛中有这样一篇文章《全面理解Java中的String数据类型》(链接http://www.phome.asia/forum/thread/19667.html) ,在这篇文章中,String s1 = new String(“kvill”),String s2 = new String(“kvill”); s1.equals(s2)为ture,说明String类中已经重写了equals()方法,如果不重写equals()方法,那么s1.equals(s2)默认比较两个对象所指向的内存地址是否相同,返回值必然为false。

?? ? ? 重写equals()方法看起来非常简单,但是有许多改写的方式会导致错误,并且后果非常严重。要想正确改写equals()方法,你必须要遵守它的通用约定。下面是约定的内容,来自java.lang.Object的规范,equals方法实现了等价关系,以下是要求遵循的5点,这5点都是当年数学的概念啊……,呵呵,且看:

1. 自反性:对于任意的引用值x,x.equals(x)一定为true。?

2. 对称性:对于任意的引用值x 和 y,当x.equals(y)返回true时,y.equals(x)也一定返回true。?

3. 传递性:对于任意的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也一定返回true。

4. 一致性:对于任意的引用值x 和 y,如果用于equals比较的对象信息没有被修改,多次调用x.equals(y)要么一致地返回true,要么一致地返回false。

5. 非空性:对于任意的非空引用值x,x.equals(null)一定返回false。

?? ? ?了解了equals重写,我们再看hashCode()这个方法,hashcode()这个方法也是从object类中继承过来的,在object类中定义如下:?

?? ? ? public native int hashCode();?

?? ? ?说明是一个本地方法,它的实现是根据本地机器相关的。再看它比较“官方”的详细说明:hashCode()返回该对象的哈希码值,该值通常是一个由该对象的内部地址转换而来的整数,它的实现主要是为了提高哈希表(例如java.util.Hashtable提供的哈希表)的性能。

?? ? ?你可以对它的这样“官方式”的定义漠视,但以下这一点你必须铭记:在每个重写了equals方法的类中,你必须也要重写hashCode方法。如果不这样做的话,就会违反Object.hashCode的通用约定,从而导致该类无法与所有基于散列值(hash)的集合类结合在一起正常运行。?

?? ? ?hashCode()的返回值和equals()的关系如下:

?? ? ?如果x.equals(y)返回“true”,那么x和y的hashCode()必须相等。?

?? ? ?如果x.equals(y)返回“false”,那么x和y的hashCode()有可能相等,也有可能不等。

说了这么多,他们之间的具体关系还是看个例子好,以下是51px中吴老师的一个例子。

源码打印?
  1. public?class?TestEquals?{??
  2. ????public?static?void?main(String?args[])?{??
  3. ????????Student?s1?=?new?Student("张一",?6);??
  4. ????????Student?s2?=?new?Student("张一",?6);??
  5. ??
  6. ????????if?(s1.equals(s2))?{??
  7. ????????????System.out.println("相同??s1的代码:"?+?s1.hashCode()?+?"??s2的代码:"??
  8. ????????????????????+?s2.hashCode());??
  9. ????????}?else?{??
  10. ????????????System.out.println("不相同");??
  11. ????????}??
  12. ????}??
  13. }??
  14. ??
  15. class?Student?{??
  16. ????private?int?age;??
  17. ????private?String?name;??
  18. ??????
  19. ????public?Student()?{??
  20. ????}??
  21. ??
  22. ????public?Student(String?name,?int?age)?{??
  23. ????????this.age?=?age;??
  24. ????????this.name?=?name;??
  25. ????}??
  26. ??
  27. ????public?int?getAge()?{??
  28. ????????return?age;??
  29. ????}??
  30. ??
  31. ????public?void?setAge(int?age)?{??
  32. ????????this.age?=?age;??
  33. ????}??
  34. ??
  35. ????public?String?getName()?{??
  36. ????????return?name;??
  37. ????}??
  38. ??
  39. ????public?void?setName(String?name)?{??
  40. ????????this.name?=?name;??
  41. ????}??
  42. ??
  43. ????public?int?hashCode()?{??
  44. ????????return?(this.name.hashCode()?+?this.age)?*?31;??
  45. ????}??
  46. ??
  47. ????public?boolean?equals(Object?obj)?{??
  48. ????????boolean?result?=?false;??
  49. ????????if?(obj?==?null)?{??
  50. ????????????result?=?false;??
  51. ????????}??
  52. ????????if?(this?==?obj)?{??
  53. ????????????result?=?true;??
  54. ????????}??
  55. ??
  56. ????????if?(obj?instanceof?Student)?{??
  57. ????????????Student?stu?=?(Student)?obj;??
  58. ????????????if?(stu.getName().equals(this.name)?&&?stu.getAge()?==?(this.age))?{??
  59. ????????????????result?=?true;??
  60. ????????????}??
  61. ??
  62. ????????}?else?{??
  63. ????????????result?=?false;??
  64. ????????}??
  65. ????????return?result;??
  66. ????}??
  67. }??

热点排行