`
qiuxia812913
  • 浏览: 7997 次
  • 性别: Icon_minigender_2
  • 来自: 成都
社区版块
存档分类
最新评论

equal hashCode == 之间关系

 
阅读更多

1、首先来回答一个问题,hashCode equal  ==  三者包含意义是什么?

 

==,当被==对象为简单类型时,比较的是值是否相同;如果被==者为对象时,== 比较的是被==对象的是否为同一对象引用,既对象物理地址是否相同。

 

equal :

源码如下:

 public boolean equals(Object obj) {
        return (this == obj);
    }

 显然在Object 对象中equal 方法是直接比较对象的物理地址是否相同。

 

再说hashCode是神马?

 

 /**
     *As much as is reasonably practical, the hashCode method defined by
     * class {@code Object} does return distinct integers for distinct
     * objects. (This is typically implemented by converting the internal
     * address of the object into an integer)
  */

public native int hashCode();

 由此可见hashCode 实质为对象存储地址。

 

 

2、qual 和 hashCode 关系如何?

 

在hashCode 方法注解中有这么一段话,如下:

If two objects are equal according to the {@code equals(Object)}method, then calling the {@code hashCode} method on each of the two objects must produce the same integer result。

如果两个对象equal , 那么两个对象产生的hashCode必须相同

 

还有如下一段话,

It is <em>not</em> required that if two objects are unequal according to the {@link java.lang.Object#equals(java.lang.Object)} method, then calling the {@code hashCode} method on each of the two objects must produce distinct integer results.  However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

翻译过来就是如果两对象的hashCode 相同,两对象并不一定equal

 

3、怎样重写eqaul 和 hashCode?

 

eqaul 方法重写必须满足以下条件,还是来看源码注解吧:

 

 /**
     * Indicates whether some other object is "equal to" this one.
     * <p>
     * The {@code equals} method implements an equivalence relation
     * on non-null object references:
     * <ul>
     * <li>It is <i>reflexive</i>: for any non-null reference value
     *     {@code x}, {@code x.equals(x)} should return
     *     {@code true}.
     * <li>It is <i>symmetric</i>: for any non-null reference values
     *     {@code x} and {@code y}, {@code x.equals(y)}
     *     should return {@code true} if and only if
     *     {@code y.equals(x)} returns {@code true}.
     * <li>It is <i>transitive</i>: for any non-null reference values
     *     {@code x}, {@code y}, and {@code z}, if
     *     {@code x.equals(y)} returns {@code true} and
     *     {@code y.equals(z)} returns {@code true}, then
     *     {@code x.equals(z)} should return {@code true}.
     * <li>It is <i>consistent</i>: for any non-null reference values
     *     {@code x} and {@code y}, multiple invocations of
     *     {@code x.equals(y)} consistently return {@code true}
     *     or consistently return {@code false}, provided no
     *     information used in {@code equals} comparisons on the
     *     objects is modified.
     * <li>For any non-null reference value {@code x},
     *     {@code x.equals(null)} should return {@code false}.
     * </ul>
     ***/
 

 

 

  • 自反性(reflexive)。对于任意不为null的引用值x,x.equals(x)一定是true

  • 对称性(symmetric)。对于任意不为null的引用值xy,当且仅当x.equals(y)true时,y.equals(x)也是true

  • 传递性(transitive)。对于任意不为null的引用值xyz,如果x.equals(y)true,同时y.equals(z)true,那么x.equals(z)一定是true

  • 一致性(consistent)。对于任意不为null的引用值xy,如果用于equals比较的对象信息没有被修改的话,多次调用时x.equals(y)要么一致地返回true要么一致地返回false

  • 对于任意不为null的引用值xx.equals(null)返回false

 

hashCode 

 

 /**
     * Returns a hash code value for the object. This method is
     * supported for the benefit of hash tables such as those provided by
     * {@link java.util.HashMap}.
     * <p>
     * The general contract of {@code hashCode} is:
     * <ul>
     * <li>Whenever it is invoked on the same object more than once during
     *     an execution of a Java application, the {@code hashCode} method
     *     must consistently return the same integer, provided no information
     *     used in {@code equals} comparisons on the object is modified.
     *     This integer need not remain consistent from one execution of an
     *     application to another execution of the same application.
     * <li>If two objects are equal according to the {@code equals(Object)}
     *     method, then calling the {@code hashCode} method on each of
     *     the two objects must produce the same integer result.
     * <li>It is <em>not</em> required that if two objects are unequal
     *     according to the {@link java.lang.Object#equals(java.lang.Object)}
     *     method, then calling the {@code hashCode} method on each of the
     *     two objects must produce distinct integer results.  However, the
     *     programmer should be aware that producing distinct integer results
     *     for unequal objects may improve the performance of hash tables.
     * </ul>
     * <p>
   ***/

 

 

  • 在一个Java应用的执行期间,如果一个对象提供给equals做比较的信息没有被修改的话,该对象多次调用hashCode()方法,该方法必须始终如一返回同一个integer。当然如果同一应用的不同执行,其返回的hashcode 不需要一致

  • 如果两个对象根据equals(Object)方法是相等,那么调用二者各自的hashCode()方法必须产生同一个integer结果。

  • 如果两对象不相等,调用二者各自的hashCode()方法生成integer结果没有说一定要求不相同。然而,程序员应该意识到对于不同的对象产生不同的integer结果,有可能会提高hash table的性能。

上述为java api 对hashCode() 和equal() 方法的规定,具体重写呢,一般根据实际需求来,但equal 大多重写跟据内容相同来做比较。hashCode 怎样重写呢?

 

下面来看一下String 的重写

 

    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }
 这里为什么会用31 这个数字,在 Effective Java是这么解释的

 

 

According to Joshua Bloch's Effective Java (a book that can't be recommended enough, and which I bought thanks to continual mentions on stackoverflow):
The value 31 was chosen because it is an odd prime. If it were even and the multiplication overflowed, information would be lost, as multiplication by 2 is equivalent to shifting. The advantage of using a prime is less clear, but it is traditional. A nice property of 31 is that the multiplication can be replaced by a shift and a subtraction for better performance: 31 * i == (i << 5) - i. Modern VMs do this sort of optimization automatically.
(from Chapter 3, Item 9: Always override hashcode when you override equals, page 48)
       根据 Joshua Bloch 的著作『Effective Java』(一本无论如何推荐都不为过的书,它是一本我根据 StackOverflow 上的不断推荐购买的书)

 


设计者选择 31 这个值是因为它是一个奇质数。如果它是一个偶数,在使用乘法当中产生数值溢出时,原有数字的信息将会丢失,因为乘以二相当于位移。

选择质数的优势不是那么清晰,但是这是一个传统。31 的一个优良的性质是:乘法可以被位移和减法替代


31 * i == (i << 5) - i

现代的 VM 可以自行完成这个优化。


来自书的第三章,条目 9 : 永远在你复写 equals 方法的时候永远复写 hashCode 方法

 

分享到:
评论

相关推荐

    【面试】hashCode与equals两者之间的关系 / == 和equals / 为什么要重写equals方法 / 重写equals /hashcode方法 / 为什么要重写hashCode方法

    文章目录1、hashCode与equals两者之间的关系2、== 和equals的区别`3、为什么要重写equals()方法?4、重写equals()方法5、为什么要重写hashCode()方法?6、什么时候需要重写hashCode()方法?7、重写hashCode()方法: ...

    string-hashcode:java.lang.String.hashCode

    字符串哈希码 字符串的其他实用程序。... equal ( code , code2 ) ;原料药hashCode(str)参数: str:字符串对象返回: 编号:哈希码返回字符串的哈希码。 请注意,哈希码对于特定字符串是不可变的。执照麻省理工学院

    java中hashcode()和equals()方法详解

    更清楚的了解hashcode()和equals()方法。

    Java中equals()与hashCode()的原理与设计

     hashCode()的返回值和equals()的关系如下:  如果x.equals(y)返回“true”,那么x和y的hashCode()必须相等。  如果x.equals(y)返回“false”,那么x和y的hashCode()有可能相等,也有可能不等。  简单的...

    Java中hashCode和equals方法的正确使用

    在这篇文章中,我将告诉大家我对hashCode和equals方法的理解。我将讨论他们的默认实现,以及如何正确的重写他们。我也将使用Apache Commons提供的工具包做一个实现。  hashCode()和equals()定义在Object类中,这...

    javaee_tedu_day09.zip

    ATM系统 Clone方法 toString方法:表示返回对象的字符串表示形式 包名.类名@hashCode(内存地址) 打印对象时,默认调用 如果不是想使用object类,toString...如果equal返回true的话,hashCode相同,重写hashCode方法

    面试官瞬间就饱了,重写equals函数,需要重写hashCode函数吗?

    面试官瞬间就饱了,重写equals函数,需要重写hashCode函数吗? 面试官问我,为什么重写equals函数,必须重写hashCode函数,我当时就懵住了。 然后扯天扯地,然后面试官瞬间就饱了,痛定思痛,写下这篇博客 首先看...

    Java-Reflection-and-Object-Comparison-in-Java:Java Reflection创建适当的对象,覆盖equal和hashCode方法

    Java中的Java反射和对象比较 项目介绍 首先,通过以下方式设计Java类: 2个私有数据成员int IntValue; 字符串StringValue; 空构造函数定义公共方法void setIntValue(int iIn){...}定义公共方法void ...

    java中重写equals和重写hashCode()

    主要介绍了java中重写equals和重写hashCode()的相关资料,需要的朋友可以参考下

    简单概括 ==跟equals的区别

    ==  == :既可以比较基本类型,也可以比较引用类型,如果...hashCode(重写equals就一定要重写hashCode)  没有重写hashCode值不会变,重写了hashCode值就会改变     总结:==跟equals的区别 1. ==既可以比较基本

    Java中的hashcode方法介绍

    主要介绍了Java中的hashcode方法介绍,还是比较不错的,这里分享给大家,供需要的朋友参考。

    Java equals 方法与hashcode 方法的深入解析

    面试时经常会问起字符串比较相关的问题,比如:字符串比较时用的什么方法,内部实现如何?hashcode的作用,以及重写equal方法,为什么要重写hashcode方法?以下就为大家解答,需要的朋友可以参考下

    解析Java对象的equals()和hashCode()的使用

     在Java语言中,equals()和hashCode()两个函数的使用是紧密配合的,你要是自己设计其中一个,要设计另外一个。在多数情况 下,这两个函数是不用考虑的,直接使用它们的默认设计可以了。但是在一些情况下,这两个...

    关于重写equals()为什么一定要重写hashcode()自己的一点心得

    首先我们看下下面代码及输出和String重写equals和hashcode的源码: package com.zzy.test; public class Test6 { public static void main(String[] args) { String s1="aaa"; String s2="aaa"; String s3=new ...

    Hibernate注释大全收藏

    定义 name 属性映射到 flight_name column, not null, can't update, length equal 50 @Column( name="columnName"; (1) 列名 boolean unique() default false; (2) 是否在该列上设置唯一约束 boolean nullable...

    Java面试题.docx

    20、Object类的equal和hashCode方法重写,为什么? 21-40题 21、List,Set,Map的区别 26、ArrayMap和HashMap的对比 29、HashMap和HashTable的区别 30、HashMap与HashSet的区别 31-40题 31、HashSet与HashMap...

    8张图理解Java

    一图胜千言,下面图解均来自Program Creek 网站的Java教程,目前它们拥有多的票选。...  如果两个对象相等(equal),那么他们一定有相同的哈希值。  如果两个对象的哈希值相同,但他们未必相等(e

    sun公司开源jar -log.jar

    sun公司开源的jar包,里面封装了log4的日志以及关于自动生成hashcode代码以及重写equal方法的jar

    学生集合排序

    将学生对象放入一个集合,通过重写学生类的hashcode与equals方法,以及通过collections工具类调用实现caparator接口类的专门比较器及方法,对存放学生的集合进行多属性排序

Global site tag (gtag.js) - Google Analytics