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

equals和hashcode

 
阅读更多

大家都说 Java 很简单,的确 Java 入门不难,但是要想深入了解 Java 那不是一朝一夕能够做到的!

学习 Java 最重要的一点是要学习其设计思想和设计理念,比如集合框架、IO框架的设计等。


通过一个实例谈谈 HashSet 与 hashCode、equals 的使用,以及在使用时的注意事项。


设计一个 Person 类,如下:

 

  1. package mark.zhang;  
  2.   
  3. public class Person {  
  4.   
  5.     private String name;  
  6.     private int age;  
  7.   
  8.     public Person(String name, int age) {  
  9.         super();  
  10.         this.name = name;  
  11.         this.age = age;  
  12.     }  
  13.   
  14.     public String getName() {  
  15.         return name;  
  16.     }  
  17.   
  18.     public int getAge() {  
  19.         return age;  
  20.     }  
  21.   
  22.     public void setName(String name) {  
  23.         this.name = name;  
  24.     }  
  25.   
  26.     public void setAge(int age) {  
  27.         this.age = age;  
  28.     }  
  29.   
  30.     @Override  
  31.     public String toString() {  
  32.         return "age=" + age + ", name=" + name;  
  33.     }  
  34.   
  35. }  


这个类很简单,两个成员变量以及 set、get 方法,注意这里没有重写 equals、hashCode 方法。为了在打印的时候方便看出结果,重写 toString 方法。


测试类也照样很简单,如下:

 

  1. public class TestPerson {  
  2.   
  3.     public static void main(String[] args) {  
  4.         Set<Person> set = new HashSet<Person>();  
  5.         Person p1 = new Person("喜洋洋"25);  
  6.         Person p2 = new Person("懒洋洋"26);  
  7.         Person p3 = new Person("灰太郎"27);  
  8.         set.add(p1);  
  9.         set.add(p2);  
  10.         set.add(p3);  
  11.         System.out.println(set.size() + " 个动画人物!");  
  12.   
  13.         for (Person person : set) {  
  14.             System.out.println(person);  
  15.         }  
  16.     }  
  17. }  

输出结果,如下所示:

 

 

  1. 3 个动画人物!  
  2. age=27, name=灰太郎  
  3. age=26, name=懒洋洋  
  4. age=25, name=喜洋洋  

ok,看懂上面的程序很简单,只要你不是初学 Java 的话!但是今天的主题不是只讨论这段代码的难易程度。

 

如果在代码中删除一个“人”,很简单,只需要调用 remove 方法即可,如下所示:

 

  1. set.remove(p2);  

 


这个时候,我需要修改 Person 这个类,重写父类 Object 的两个方法,equals、hashCode,修改之后的代码:

 

  1. package mark.zhang;  
  2.   
  3. public class Person {  
  4.   
  5.     private String name;  
  6.     private int age;  
  7.   
  8.     public Person(String name, int age) {  
  9.         super();  
  10.         this.name = name;  
  11.         this.age = age;  
  12.     }  
  13.   
  14.     public String getName() {  
  15.         return name;  
  16.     }  
  17.   
  18.     public int getAge() {  
  19.         return age;  
  20.     }  
  21.   
  22.     public void setName(String name) {  
  23.         this.name = name;  
  24.     }  
  25.   
  26.     public void setAge(int age) {  
  27.         this.age = age;  
  28.     }  
  29.   
  30.     @Override  
  31.     public String toString() {  
  32.         return "age=" + age + ", name=" + name;  
  33.     }  
  34.   
  35.     @Override  
  36.     public int hashCode() {  
  37.         final int prime = 31;  
  38.         int result = 1;  
  39.         result = prime * result + age;  
  40.         result = prime * result + ((name == null) ? 0 : name.hashCode());  
  41.         return result;  
  42.     }  
  43.   
  44.     @Override  
  45.     public boolean equals(Object obj) {  
  46.         if (this == obj)  
  47.             return true;  
  48.         if (obj == null)  
  49.             return false;  
  50.         if (getClass() != obj.getClass())  
  51.             return false;  
  52.         Person other = (Person) obj;  
  53.         if (age != other.age)  
  54.             return false;  
  55.         if (name == null) {  
  56.             if (other.name != null)  
  57.                 return false;  
  58.         } else if (!name.equals(other.name))  
  59.             return false;  
  60.         return true;  
  61.     }  
  62.   
  63. }  

在测试类中,开始这样子做:

 

 

  1. public class TestPerson {  
  2.   
  3.     public static void main(String[] args) {  
  4.         Set<Person> set = new HashSet<Person>();  
  5.         Person p1 = new Person("喜洋洋"25);  
  6.         Person p2 = new Person("懒洋洋"26);  
  7.         Person p3 = new Person("灰太郎"27);  
  8.         set.add(p1);  
  9.         set.add(p2);  
  10.         set.add(p3);  
  11.         System.out.println(set.size() + " 个动画人物!");  
  12.         // 删除一个对象  
  13.         set.remove(p2);  
  14.         System.out.println("删除之后," + set.size() + " 个动画人物!");  
  15.         for (Person person : set) {  
  16.             System.out.println(person);  
  17.         }  
  18.     }  
  19. }  

打印结果:

 

 

  1. 3 个动画人物!  
  2. 删除之后,2 个动画人物!  
  3. age=27, name=灰太郎  
  4. age=25, name=喜洋洋  

成功删除一个对象,再次修改测试类的代码:

 

 

  1. public class TestPerson {  
  2.   
  3.     public static void main(String[] args) {  
  4.         Set<Person> set = new HashSet<Person>();  
  5.         Person p1 = new Person("喜洋洋"25);  
  6.         Person p2 = new Person("懒洋洋"26);  
  7.         Person p3 = new Person("灰太郎"27);  
  8.         set.add(p1);  
  9.         set.add(p2);  
  10.         set.add(p3);  
  11.         System.out.println(set.size() + " 个动画人物!");  
  12.         // 修改对象属性  
  13.         p2.setName("美人鱼");  
  14.         // 删除一个对象  
  15.         set.remove(p2);  
  16.         System.out.println("删除之后," + set.size() + " 个动画人物!");  
  17.         for (Person person : set) {  
  18.             System.out.println(person);  
  19.         }  
  20.     }  
  21. }  

打印结果:

 

 

  1. 3 个动画人物!  
  2. 删除之后,3 个动画人物!  
  3. age=26, name=美人鱼  
  4. age=27, name=灰太郎  
  5. age=25, name=喜洋洋  

这次怪了,明明删除一个了,怎么还是有三个呢?你会发现,的确删除一个“懒洋洋”,但是“美人鱼”没有被删除!

 

如果你在 Person 类中,不重写 hashCode 方法,不会有这种现象发生!


这里说明一个问题:添加到集合的类,不要轻易去修改该类对象的属性,否则 remove() 方法无效。同理 contains() 方法也会无效。


如果有兴趣的话,可以看看其源码,可以看出这与 hashCode() 方法有很大关系!


再说一个容易让人误解的问题:

Collection接口的子接口 List 和 Set,Set (包括其子类)无序不可重复,List (包括其子类)有序可重复,所谓有序无序是相对于 add 的程序执行顺序来说的。


换句话说,对于上面的 List、Set 以及其子类等,如果 equals 为 true 的话,就算是重复的对象。这里的 equals 比较的是内容,不是对象地址。
只不过,对于 Set 来说不可以添加重复对象,对于 List 来说可以添加重复对象!


对于添加对象到Set集合中,从源码可以看出其流程是这样子的:


将对象放入到集合中时,首先判断要放入对象的hashcode值与集合中的任意一个元素的hashcode值是否相等,如果不相等直接将该对象放入集合中。
如果hashcode值相等,然后再通过equals方法判断要放入对象与集合中的任意一个对象是否相等,如果equals判断不相等,直接将该元素放入到集合中,否则不放入。


举个例子,注意:Person 要重写 hashCode、equals 方法:

 

  1. public static void main(String[] args) {  
  2.         LinkedList<Person> list = new LinkedList<Person>();  
  3.         Set<Person> set = new HashSet<Person>();  
  4.         Person p1 = new Person("喜喜"3);  
  5.         Person p2 = new Person("喜喜"3);  
  6.         System.out.println("stu1 == stu2 : " + (p1 == p2));  
  7.         System.out.println("stu1.equals(stu2) : " + p1.equals(p2));  
  8.         // list可以重复  
  9.         list.add(p1);  
  10.         list.add(p2);  
  11.         System.out.println("list size:" + list.size());  
  12.         // set 不可以重复  
  13.         set.add(p1);  
  14.         set.add(p2);  
  15.         System.out.println("set size:" + set.size());  
  16.     }  

 


打印结果:

 

  1. stu1 == stu2 : false  
  2. stu1.equals(stu2) : true  
  3. list size:2  
  4. set size:1  

感谢下面两篇博客,我只是在它们的基础之上添枝加叶。

分享到:
评论

相关推荐

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

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

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

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

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

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

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

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

    Java中的equals和hashCode方法详解1

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

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

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

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

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

    深入理解equals和hashCode方法

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

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

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

    equals,hashcode,toString

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

    Java equals 和 hashCode 的这几个问题可以说明白吗?.docx

    图文并茂吃透面试题,看完这个,吊打面试官,拿高薪offer!

    Java中equals,hashcode和==的区别

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

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

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

    equals与hashCode方法讲解

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

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

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

    equals-hashcode-processor-1.0.0.zip

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

    学习Object类——为什么要重写equeals和hashcode方法

    Object 类的 equals 和 hashCode 方法的重要性与实现 在 Java 编程语言中,Object 类是所有类的父类,但是在实际开发中,我们往往需要重写 Object 中的 equals 和 hashCode 方法,以便正确地比较对象的逻辑内容,而...

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

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

    hashcode和equals方法

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

    java集合——Java中的equals和hashCode方法详解

    在Java编程语言中,`equals()` 和 `hashCode()` 方法是Object类中定义的基本方法,所有类都默认继承自Object类,因此每个Java对象都有这两个方法。这两个方法在处理集合类,尤其是Set接口的实现(如HashSet)时起着...

Global site tag (gtag.js) - Google Analytics