hashCode和equal二三事

来源:互联网 发布:java物联网开发技术 编辑:程序博客网 时间:2024/04/19 23:55

关于equal经常用到,hashCode一直很抽象,很少用到,但又时时用到。

equals

有2个String

String s1 =new String( "aa");

String s2 = new String("bb");

s1.equals(s2);      输出true

有一个Student 类(没有重写equal方法)  2个对象

Student stu1 = new Student("张三");

Student stu2 = new Student("张三");

stu1.equals(stu2);     输出false;


同样是2组对象,为什么返回不一样呢?

所有类都继承了Object类,

因为String类本身已经重写了Object类中的equals方法,String调用equals方法时,比较的是他们的内容是否相等,s1和s2的内容相同,所以s1.equals(s2)为true。而且,String也重写了hashCode方法


而Student类没有重写Object类中的equals,而没有重写的Objec类中的equals方法比较的是2个对象的地址是否相同,stu1和stu2都是new 出来的对象,地址当然不同,所以

stu1.equals(stu2)为false

hashcode

hashcode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值。public int hashCode()返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。

哈希码产生的依据:哈希码并不是完全唯一的,它是一种算法,让同一个类的对象按照自己不同的特征尽量的有不同的哈希码,但不表示不同的对象哈希码完全不同。也有相同的情况,看程序员如何写哈希码的算法。

也就是说相互equals的两个对象,要保证他们的hashCode相同(使他们相同的原因主要是可以根据hashcode的值取的相应的对象,目的提高取对象的效率),

注意:但是在自定的类中如果只是重写了equals方法,却没有重写hashcode方法,就使得2个对象相互equals,但是他们的hashCode不一致(参见上一篇转载的博客)


hash code是一种编码方式,在Java中,每个对象都会有一个hashcode,Java可以通过这个hashcode来识别一个对象。至于hashcode的具体编码方式,比较复杂(事实上这个编码是可以由程序员通过继承和接口的实现重写的)。而hashtable等结构,就是通过这个哈希实现快速查找键对象。这是他们的内部联系,但一般编程时无需了解这些,只要知道hashtable实现了一种无顺序的元素排列就可以了

查阅资料得到以下java语言的定义
1) 对象相等则hashCode一定相等;
2) hashCode相等对象未必相等。
这也涉及到如何写自定义的hashCode方法的问题:必须符合以上条件。注意条件2中的未必。具体可参见java doc; Effective Java中有更详细论述


为什么要重写hashCode方法?

查看资料得知:

先了解java判断两个对象是否相等的规则

在java的集合中,判断两个对象是否相等的规则是:

首先,判断两个对象的hashCode是否相等

1、如果不相等,认为两个对象也不相等,这也反面说明对象相等怎hashcode就相等。


2.1如果相等,则判断两个对象用equals运算是否相等(因为hashcode相等但是对象不一定相等,这时就要equals来判断了)
2.2如果不相等,认为两个对象也不相等
2.3如果相等,认为两个对象相等

有人会问既然最后还是靠equals判断对象是否相等,为什么还要用到hashCode呢,查阅资料和参看达人博客,本人得到下面的答案:
我们在equals方法中需要向下转型,效率很低,所以先判断hashCode方法可以提高效率。在hashCode相同的情况下,再利用equals,总之一切都是为了效率

所以Java自定义了是可以根据hashCode直接判断2个对象是否相等,就要保证相互equals对象,他们的hashcode相等。所以简单来讲,hashcode相当于是一个对象的编码。

当要比较对象的内容而不比较引用时便重写equals方法 但重写equals方法便一定要重写hashcode方法,java机制会在调用equals方法时自动先调用hashcode方法


关于重写equals和hashCode方法给出一个例子

 class Key {              private Integer id;              private String value;                            public Key(Integer id, String value) {                  super();                  this.id = id;                  this.value = value;              }              @Override              public boolean equals(Object o) {                  if(o == null || !(o instanceof Key_)) { //判断类型转换                     return false;                  }else {                      return this.id.equals(((Key)o).id);  //id相同则equals,则返回true。保证相同的key内容相同的对象相互equals                }              }              @Override              public int hashCode() {                   return id.hashCode(); //id是String类型,String重写了equals和hashCode,相同id,其hashcode一定相同             }                         }

关于hashCode的理解,也许会有失误,欢迎批评指正。

hashCode的作用参考:http://blog.csdn.net/chinayuan/article/details/3345559








原创粉丝点击