`
qiuxia812913
  • 浏览: 8432 次
  • 性别: 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 方法

 

分享到:
评论

相关推荐

    string-hashcode:java.lang.String.hashCode

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

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

    本文将详细介绍这两个方法的工作原理、使用场景以及它们之间的关系。 #### `hashCode()`方法 `hashCode()`方法定义于`Object`类中,它是Java语言的基础类,所有Java类都直接或间接地继承自`Object`。`hashCode()`的...

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

    【面试】中提到的几个关键知识点集中在对象比较、equals()和hashCode()方法的使用以及它们之间的关系上。这些概念在Java编程中至关重要,特别是在处理集合类和比较对象时。 1、**hashCode与equals两者之间的关系**...

    关于hashCode()和equals()的本质区别和联系

    hashCode() 和 equals() 方法之间存在着非常重要的关系。如果两个对象是相等的,那么它们必须有相同的哈希码值。否则,如果两个对象的哈希码值不同,那么它们不能被认为是相等的。 为什么需要重写 hashCode() 和 ...

    java中 == 与 equal 的区别讲解

    System.out.println("equal比较:" + str1.equals(str2)); // 输出 true ``` 在这里,`str1.equals(str2)` 返回 `true`,因为两个字符串对象的内容是相同的。 接下来,我们回顾 `equals()` 方法的五个特性: 1. *...

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

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

    与==的区别.docxequal与==的区别.docx

    在Java编程语言中,`equals()`方法和`==`运算符是用于比较对象之间关系的两种常见方式,但它们有着显著的区别。理解这些差异对于编写正确的代码至关重要。 首先,`==`运算符主要用于比较基本类型(如int、char、...

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

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

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

    在Java编程语言中,`equals()` 和 `hashCode()` 方法是对象的基本组成部分,它们与对象的比较和哈希表(如 `HashMap`)的操作密切相关。在面试中,面试官提出的问题直指这两个方法的重要关联。 首先,`equals()` ...

    javaee_tedu_day09.zip

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

    Java中的hashcode方法介绍

    Java中的`hashCode`方法是Java编程语言中的一个重要概念,它主要与对象的散列处理相关。在Java的`Object`类中定义了一个本地方法(native)`hashCode()`,该方法返回一个`int`类型的数值。这个数值是根据对象的状态...

    java中重写equals和重写hashCode()

    在Java编程语言中,`equals()` 和 `hashCode()` 是两个非常重要的方法,它们主要用于比较对象的平等性以及在散列数据结构(如 `HashMap`、`HashSet` 等)中的对象定位。当我们创建自定义类时,有时需要根据业务需求...

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

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

    关于重写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 ...

    C#获取当前时间的各种格式

    bool isEqual = dt.Equals(anotherDt); ``` 20. 获取日期和时间的哈希码 使用 `GetHashCode()` 方法可以获取日期和时间的哈希码,例如: ``` int hashCode = dt.GetHashCode(); ``` 21. 获取日期和时间的类型 使用...

    C# datetime操作

    `CompareTo()` 方法用于比较两个`DateTime`对象并返回一个整数值,指示它们之间的相对顺序;`Equals()` 方法则用于检查两个`DateTime`对象是否相等。 #### 获取日期和时间的哈希码 ```csharp int hashCode = dt....

    简单概括 ==跟equals的区别

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

    JAVA 枚举相关知识汇总

    boolean isEqual = Color.GREEN.equals(Color.GREEN); 枚举类型的每个枚举常量可以使用 compareTo() 方法比较,例如: int compareTo = Color.GREEN.compareTo(Color.GREEN); 枚举类型的每个枚举常量可以使用 ...

    java个人总结.docx

    但是,两个`hashCode()`相等的对象并不一定`equal()`相等,因为不同的对象可能会有相同的`hashCode`值。 对象序列化是一个重要的概念,它允许将Java对象的状态转化为字节流,以便持久化或在网络上传输。要序列化一...

    学生集合排序

    本文将详细探讨如何实现这个过程,重点在于重写`hashCode`和`equals`方法,以及利用`Collections`工具类和自定义比较器来实现多属性排序。 首先,让我们了解`hashCode`和`equals`方法的重要性。这两个方法是Java中...

Global site tag (gtag.js) - Google Analytics