zoukankan      html  css  js  c++  java
  • Java中Set的contains()方法——hashCode与equals方法的约定及重写原则

    转自:http://blog.csdn.net/renfufei/article/details/14163329
    翻译人员: 铁锚
    翻译时间: 2013年11月5日
    本文主要讨论 集合Set 中存储对象的 hashCode 与 equals 方法应遵循的约束关系.

    新手对Set中contains()方法的疑惑
    [java] view plain copy
     
    1. import java.util.HashSet;  
    2.    
    3. class Dog{  
    4.     String color;  
    5.    
    6.     public Dog(String s){  
    7.         color = s;  
    8.     }     
    9. }  
    10.    
    11. public class SetAndHashCode {  
    12.     public static void main(String[] args) {  
    13.         HashSet dogSet = new HashSet();  
    14.         dogSet.add(new Dog("white"));  
    15.         dogSet.add(new Dog("white"));  
    16.    
    17.         System.out.println("We have " + dogSet.size() + " white dogs!");  
    18.    
    19.         if(dogSet.contains(new Dog("white"))){  
    20.             System.out.println("We have a white dog!");  
    21.         }else{  
    22.             System.out.println("No white dog!");  
    23.         }     
    24.     }  
    25. }  

    上述代码的输出为:
    [plain] view plain copy
     
    1. We have 2 white dogs!  
    2. No white dog!  

    程序中添加了两只白色的小狗到集合dogSet中. 且 size()方法显示有2只白色的小狗.但为什么用 contains()方法来判断时却提示没有白色的小狗呢?

    Set的contains(Object o) 方法详解
    Java的API文档指出: 当且仅当 本set包含一个元素 e,并且满足(o==null ? e==null : o.equals(e))条件时,contains()方法才返回true. 因此 contains()方法 必定使用equals方法来检查是否相等.
    需要注意的是: set 中是可以包含 null值的(常见的集合类都可以包含null值). 所以如果添加了null,然后判断是否包含null,将会返回true,代码如下所示:
    [java] view plain copy
     
    1. HashSet a = new HashSet();  
    2. a.add(null);  
    3. if(a.contains(null)){  
    4.     System.out.println("true");  
    5. }  

    Java的根类Object定义了  public boolean equals(Object obj) 方法.因此所有的对象,包括数组(array,[]),都实现了此方法。
    在自定义类里,如果没有明确地重写(override)此方法,那么就会使用Object类的默认实现.即只有两个对象(引用)指向同一块内存地址(即同一个实际对象, x==y为true)时,才会返回true。
    如果把Dog类修改为如下代码,能实现我们的目标吗?
    [java] view plain copy
     
    1. class Dog{  
    2.     String color;  
    3.    
    4.     public Dog(String s){  
    5.         color = s;  
    6.     }  
    7.    
    8.     //重写equals方法, 最佳实践就是如下这种判断顺序:  
    9.     public boolean equals(Object obj) {  
    10.         if (!(obj instanceof Dog))  
    11.             return false;     
    12.         if (obj == this)  
    13.             return true;  
    14.         return this.color == ((Dog) obj).color;  
    15.     }  
    16.    
    17. }  
    英文答案是: no.

    问题的关键在于 Java中hashCode与equals方法的紧密联系. hashCode() 是Object类定义的另一个基础方法.

    equals()与hashCode()方法之间的设计实现原则为:
    如果两个对象相等(使用equals()方法),那么必须拥有相同的哈希码(使用hashCode()方法).
    即使两个对象有相同的哈希值(hash code),他们不一定相等.意思就是: 多个不同的对象,可以返回同一个hash值.

    hashCode()的默认实现是为不同的对象返回不同的整数.有一个设计原则是,hashCode对于同一个对象,不管内部怎么改变,应该都返回相同的整数值.
    在上面的例子中,因为未定义自己的hashCode()实现,因此默认实现对两个对象返回两个不同的整数,这种情况破坏了约定原则。

    解决办法
    [java] view plain copy
     
    1. class Dog{  
    2.     String color;  
    3.    
    4.     public Dog(String s){  
    5.         color = s;  
    6.     }  
    7.    
    8.     //重写equals方法, 最佳实践就是如下这种判断顺序:  
    9.     public boolean equals(Object obj) {  
    10.         if (!(obj instanceof Dog))  
    11.             return false;     
    12.         if (obj == this)  
    13.             return true;  
    14.         return this.color == ((Dog) obj).color;  
    15.     }  
    16.    
    17.     public int hashCode(){  
    18.         return color.length();//简单原则  
    19.     }  
    20. }  

    --------------------------------------------------------------------------------

    关注微信公众号(测试工程师小站)即可在手机上查阅,并可接收更多测试分享,发送【测试资料】更可获取百G测试教程~

  • 相关阅读:
    Linux Shell 1>/dev/null 2>&1 含义
    iSCSI存储的3种连接方式
    Linux Shell远程执行命令(命令行与脚本方式)
    VIM常用命令
    RHEL6.2配置从零开始
    shell 正则表达式与文件名匹配
    Java中判断非空对象.
    Facebook的时序数据库技术(上)
    SpringBoot+SpringCache实现两级缓存(Redis+Caffeine)
    Swagger模型字段排序问题
  • 原文地址:https://www.cnblogs.com/songzhenhua/p/9312736.html
Copyright © 2011-2022 走看看