`
xiangdefei
  • 浏览: 58277 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

浅淡equals()和hashcode()

 
阅读更多
以前对Object类的equals()方法和hashcode()方法很模糊,只知道用equals()来判断两个对象是否相等,hashcode()是来计算散列值的,重写equals()方法时,总是要重写hashcode(),却不知道为什么要这样,昨天在家研究了一天,终于弄懂了一点点,所以写下来加深印象,不懂的同学也可以看看。

   在网上查了很多资料,但是都写得不明不白的,压根写那些资料的人自己都不明白,还出来误导人!靠你大爷的。于是我查了Effective+java,think in java 两本书,但是里面有些讲得很难懂(大师们写得太深奥了!!) ,加之又是看英文翻译过来的中文版,(-.-|||....   好后悔以前没有认真滴学英语) 所以看起来很费力。于是我就把里面的每一句话都理解然后再写代码做测试。好了,不啰嗦了。切入正题!

       想必大家都知道,equals()方法和hashcode()方法都是从Object类中继承过来的。而String ,Integer、Double。Float等值类的这些封装类都重写了Object中的equals()方法,让它们不再比较引用,而是比较对象中实际包含的值,即比较的是内容。
    而Object的equals()方法比较的是地址值(也是比较引用是否相同)。

equals()方法在Object类中是这样定义的:

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



String,Integer等封装类重写Obejct类的equals()方法,大家自己看吧 。


      首先请问一下,判断java两个对象是否相等的规则是什么?

     比较两个对象是否相等,首先比较两个对象的hashcode值是否相等,如果hashcode值不相等的话,那么我们认为这两个对象肯定不相等,如果hashcode值相等,那么我们再用equals(Ojbect)比较一下这两个对象是否相等,如果不相等,我们认为这两个对象不相等,如果相等,这两个对象肯定相等,也就是说如果两个对象根据equals(Object)方法是相等的,那么调用两个对象中任何一个对象的hashcode方法必须产生相同的值 ,反之,如果两个对象根据equals(Object)方法是不相等的,那么调用两个对象中任何一个对象的hashcode方法不要求必须产生不相同的值(既两个对象equals()不相等,它们也有可能有相等的hashcode值)  ,也或者可以这么说:两个对象hashcode()不相等,那么equals()肯定不相等,两个对象hashcode相等,equals()有可能相等,也有可能不相等。OK?明白了不?(观众:靠你大爷的,咋这么绕?都被你说糊涂了)。那上面的话有什么根据呢?我来解释一下

Object类是这样定义hashcode()方法的:

Public native int hashcode()  ;


说明hashcode()是一个本地方法,返回的是对象的地址值,而Object类的equals()方法是比较两个对象地址值的,如果equals()相等,那么说明两个对象具有相等的地址值,所以hashcode()值也相等。在String,Integer等类中,equals()方法是比较两个对象的内容,当两个对象内容相等时,Hashcode()方法根据String等类的重写(这个前面已经分析了)代码的分析,也可知道hashcode()返回结果也会相等。

一般来说,如果你要把一个类的对象放入容器中,那么通常要为其重写equals()方法,让他们比较地址值而不是内容值。特别地,如果要把你的类的对象放入散列表容器中(Hashtable、HashMap、HashSet、LinkedHashMap),那么还要重写hashCode()方法;要放到有序容器中,还要重写compareTo()方法。那么下面解释一下为什么要重写equals()和hashcode()?(这也是本文的重点)(观众:靠你大爷的,那你前面说的那些都是废话么?答:NO NO NO,前面说的都是为这个做铺垫,如果你看不懂前面说的那些,这个....)

下面我们用Set容器做例子:

我们都知道Set不能存储相同的元素,元素的位置也是不确定的(无序的)。那么Set又是怎么去判断是否有重复对象的呢?前面有解释(看看看…明白了上面说的不是废话了吧),不废话,写段代码测试一下,这样更明白点:

public static void main(String args[]){

String str1=new String("xiangdefei");

       String str2=new String("xiangdefei");

       Set set=new HashSet();

       set.add(str1);

       set.add(str2);

       System.out.println(str1==str2);

       System.out.println(str1.hashCode()==str2.hashCode());

       System.out.println("str1.hashcode:"+str1.hashCode());

       System.out.println("str2.hashcode:"+str2.hashCode());

       System.out.println(str1.equals(str2));    

       Iterator ite=set.iterator();

       while(ite.hasNext()){

           System.out.println(ite.next());

       }

}

打印结果:

False

true

str1.hashcode:523358144

str2.hashcode:523358144

true

xiangdefei



果在我们预料之中,在while循环里只打印了一个:xiangdefei,

因为String类重写了equals()和hashcode()方法,我们也看到了这两个String类的对象的hashcode值相等,都是523358144,所以集合认定这两个对象相等,所以不重复添加。

但是我们看看下面这个例子:

这是一个普通的类Student(现在没有为这个类重写equals()和hashcode()方法,只重写了toString()方法(方便等下打印结果)):

public class Student {

    private String name;

    private int age;

    

 

    public String getName() {

       return name;

    }

    public void setName(String name) {

       this.name = name;

    }

    public int getAge() {

       return age;

    }

    public void setAge(int age) {

       this.age = age;

    }

public String toString(){

       return this.name+":"+this.age;

    }

}

Main方法:

public static void main(String args[]){

Student student1=new Student("xiangdefei",1);

       Student student2=new Student("xiangdefei",1);

       Set set=new HashSet();

       set.add(student1);

       set.add(student2);

       System.out.println(student1==student2);

       System.out.println(student1.hashCode()==student2.hashCode());

       System.out.println(student1.hashCode());

       System.out.println(student2.hashCode());

       System.out.println(student1.equals(student2));

       Iterator ite=set.iterator();

       while(ite.hasNext()){

           System.out.println(ite.next());

       }

}

打印结果为:

false

false

33311724

14452073

false

xiangdefei:1

xiangdefei:1




是不是郁闷了?为什么Set集合添加了重复元素?

仔细看看两个对象的hashcode值,不相等。那么equals()比较也不相等。所以容器认为它们是不相等的元素,进行了重复添加。它们为什么没有产生相等的hashcode值呢,前面的例子的两个对象不都产生了相等的hashcode值了吗?前面解释了,String类重写了Object类的equals()和hashcode(),而这个Student类没有重写equals()和hashcode()方法。所以集合在比较这两个对象用的是Object类的hashcode(),各位还记得hashcode是比较什么的吗?(观众:你丫的哪来的这么多问题?自己回答!!!),是的,前面提过hashcode()比较的是对象的地址值(对象的引用),而我们使用new创建的两个对象,两个对象的地址值当然不一样,所以Set把它们当作两个不同的对象,那怎么办呢?

对了,就是在Student类中重写Object类的equals()和 hashcode()方法

public class Student {

    private String name;

    private int age;

    

 

    public String getName() {

       return name;

    }

    public void setName(String name) {

       this.name = name;

    }

    public int getAge() {

       return age;

    }

    public void setAge(int age) {

       this.age = age;

    }

public String toString(){

       return this.name+":"+this.age;

    }

 

@Override

    public int hashCode() {

       final int prime = 31;

       int result = 1;

       result = prime * result + age;

       result = prime * result + ((name == null) ? 0 : name.hashCode());

       return result;

    }

    @Override

    public boolean equals(Object obj) {

       if (this == obj)

           return true;

       if (obj == null)

           return false;

       if (getClass() != obj.getClass())

           return false;

       Student other = (Student) obj;

       if (age != other.age)

           return false;

       if (name == null) {

           if (other.name != null)

              return false;

       } else if (!name.equals(other.name))

           return false;

       return true;

    }

}

修改Student类,如果再运行一下前面的main方法则是打印这样的结果:

false

true

523359136

523359136

true

xiangdefei:1





产生了相同的hashcode值,所以Set集合认为这两个对象是相等的,只添加了一个元素。

关于如何在类中重写equals()和hashcode()方法,今天就不说了,我自己也是半懂不懂的。等弄懂了,下次再写吧。好累!(观众:鼓掌!!!!)

2
2
分享到:
评论

相关推荐

    重写equals和hashcode方法_equals_重写equals和hashcode方法_

    在Java编程语言中,`equals()` 和 `hashCode()` 方法是Object类中的两个核心方法,所有类都默认继承自Object类。这两个方法在处理对象比较和集合操作时起着至关重要的作用。当我们创建自定义类并需要对对象进行精确...

    equals与hashCode在实际开发中的重写写法

    在Java编程语言中,`equals()` 和 `hashCode()` 方法是两个非常重要的成员,尤其是在处理对象比较和集合操作时。这两个方法通常与`Object`类中的默认实现相关联,但为了在实际开发中实现正确的对象比较和哈希表操作...

    equals,hashcode,toString

    在Java编程语言中,`equals()`, `hashCode()` 和 `toString()` 是三个非常重要的方法,它们主要用于对象的比较、哈希存储以及打印对象信息。这三个方法是Java对象的基础特性,对于理解和开发高质量的Java程序至关...

    Java中equals,hashcode和==的区别

    "Java中equals、hashcode和==的区别" Java 中 equals、hashcode 和==的区别是 Java 编程语言中一个经常遇到的问题。这三个概念都是用来比较对象的,但是它们之间存在着本质的区别。 首先,==号是Java中的一个...

    Java容器集合(equals 和 hashCode+基础数据结构+ArrayList+Vector和LinkedList)

    Java容器集合(equals和hashCode+基础数据结构+ArrayList+Vector和LinkedList) Java容器集合是Java中的一种基础数据结构,用于存储和管理数据。其中,equals和hashCode方法是Java容器集合中两个非常重要的方法,...

    Java理论与实践:hashCode()和equals()方法

    本文还介绍了定义对象的相等性、实施equals()和hashCode()的需求、编写自己的equals()和hashCode()方法。通过统一定义equals()和hashCode(),可以提升类作为基于散列的集合中的关键字的使用性。

    equals与hashCode方法讲解

    equals 方法和 hashCode 方法是 Java 语言中两个重要的方法,它们都是在 Object 类中定义的。equals 方法用于比较两个对象是否相等,而 hashCode 方法用于返回对象的哈希码。 在 Java 的 Object 类中,equals 方法...

    Java中的equals和hashCode方法详解1

    在Java编程语言中,`equals()`和`hashCode()`方法是对象的基本组成部分,它们主要用于对象的比较和存储。这两个方法在`java.lang.Object`类中定义,因此所有的Java类都默认继承了这两个方法。然而,根据具体的应用...

    equals-hashcode-processor-1.0.0.zip

    在Scala中,正确实现`equals`和`hashCode`方法对于集合操作至关重要,因为它们影响了对象在Set和Map中的存储和查找。这个处理器可能提供了一种自动化的方式来生成这些方法,避免了手动实现时可能出现的错误和不一致...

    equals 和 hashCode两者效果分析详解.docx

    在Java编程语言中,`equals()`和`hashCode()`方法是两个非常重要的概念,尤其是在处理对象比较和容器(如HashMap和HashSet)操作时。这两个方法在Java的类库中有着核心地位,尤其是对于类实例的比较和存储。接下来,...

    关于Object中equals方法和hashCode方法判断的分析

    "关于Object中equals方法和hashCode方法判断的分析" 在 Java 中,Object 类提供了两个重要的方法:equals 方法和 hashCode 方法。这两个方法都是用于比较两个对象是否相等的,但它们的实现机理和作用域却有所不同。...

    关于重写equals,hashcode以及compareTo方法!

    重写equals()、hashcode()和compareTo()方法是非常重要的,它可以使我们的程序更加高效、可靠和灵活。在实际开发中,我们需要根据具体情况来决定是否需要重写这些方法,并遵守相关的规则,以避免出现意想不到的结果...

    Java重写equals同时需要重写hashCode的代码说明

    Java重写equals同时需要重写hashCode的代码说明,以及如何重写hashCode方法,此代码演示按照effective java书籍说明的重写思路。代码中演示了使用集合存储对象,并且对象作为key,需重写equals和hashCode.

    hashcode和equals方法

    equals()和hashcode()这两个方法都是从object类中继承过来的。当String 、Math、还有Integer、Double。。。。等这些封装类在使用equals()方法时,已经覆盖了object类的equals()方法.

    深入理解equals和hashCode方法

    深入理解equals和hashCode方法 equals和hashCode方法是Java中Object类提供的两个重要方法,对以后的学习有很大的帮助。本文将深入剖析这两个方法,帮助读者更好地理解和使用它们。 equals方法 equals方法是用于...

    Java重写equals及hashcode方法流程解析

    Java中的equals和hashCode方法是两个非常重要的方法,它们都是Object类中的方法。在实际开发中,正确地重写这两个方法对于确保程序的正确性和性能至关重要。下面,我们将详细地介绍Java重写equals及hashCode方法的...

    Java_重写equals()和hashCode()

    在Java编程语言中,`equals()` 和 `hashCode()` 方法是对象的基本组成部分,它们在很多场景下都发挥着至关重要的作用。这两个方法与对象的相等性比较和哈希表(如HashMap、HashSet)的运作紧密相关。这篇博客将深入...

    JAVA集合的使用(List、Map、Set、Queue,Collections、Comparable与Comparator,排序、搜索,内部类、equals、hashCode)

    要注意的是List,Set,Queue继承了Collection接口,...这里想用一个简单的例子展示一下他们的使用,内容包括:List、Map、Set、Queue,Collections、Comparable与Comparator,排序、搜索,内部类,泛型、重写equals、hashCode

    ordinary-zhang#java#equals和hashcode方法详解1

    1.概述 2.为什么重写equels方法要重写hashcode方法 3.例子

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

    hashCode() 和 equals() 的本质区别和联系 Java 中的每个对象都有 hashCode() 和 equals() 方法,这两个方法的正确实现对于 Java 开发人员来说是非常重要的。本文将详细介绍 hashCode() 和 equals() 的本质区别和...

Global site tag (gtag.js) - Google Analytics