zoukankan      html  css  js  c++  java
  • equals()和hashCode()之间的关系

    在Java的基类java.lang.Object中有两个非常重要的方法:

    public boolean equals(Object obj)
    public int hashCode()

    对这两个方法的理解非常重要,特别是当用户自己定义对象,并将其存入到Map中的时候;

    然而,即便是高级开发人员,有时候也搞不清楚如何正确的使用它们;

    在这篇文章,我首先会展示一种常见的错误示例,然后解释如何正确的使用这两个方法;

    常犯的错误

    如下代码是常见的错误使用示例:

    package simplejava;
    
    import java.util.HashMap;
    
    class Apple {
        private String color;
    
        public Apple(String color) {
            this.color = color;
        }
    
        public boolean equals(Object obj) {
            if (!(obj instanceof Apple))
                return false;
            if (obj == this)
                return true;
            return this.color.equals(((Apple) obj).color);
        }
    
    }
    
    public class Q9 {
        public static void main(String[] args) {
            Apple a1 = new Apple("green");
            Apple a2 = new Apple("red");
            // hashMap stores apple type and its quantity
            HashMap<Apple, Integer> m = new HashMap<Apple, Integer>();
            m.put(a1, 10);
            m.put(a2, 20);
            System.out.println(m.get(new Apple("green")));
        }
    }

    在这个例子中,一个绿色苹果对象成功存入到hashMap中,但是当我们要取出来的时候,得到的却是null;然而通过调试程序,我们确实看到了hashmap中的绿苹果对象;

    错误原因-hashcode()方法导致

    之所以出现这个错误是因为没有重写hashCode()方法导致的。

    hashCode()和equals()的关系是这样的:

    如果两个对象相等(equal),它们的hashcode一定相同;

    如果两个对象有相同的hashcode,它们不一定相等(equal);

    之所以这样设计是为了在Map中更快的查找到对象(相对于线性搜索);

    一般Map都设计成数组+链表的结构,使用hashcode去查找对象需要两个步骤,首先使用hashcode定位数组下标索引,然后遍历该数组元素对应的链表,找到equals的元素;

    Object默认的hashcode实现对于不同的对象会返回不同的值,因此,在上面那个例子中,不同的对象(即使同一个类型)有着不同的hashcode;

    值的散列就像在车库储存货物,不同的货物能被存放到不同的车库。比较有效查找货物办法是将不同的货物存到不同的车库中,而不是同一个车库;

    所以将hash值尽可能的分散是一个比较好的策略;

    关于这个例子,解决办法是添加hashcode方法,这里我将使用颜色的长度作为示范,如下代码:

    public int hashCode(){
        return this.color.length();
    }

    译文链接:http://www.programcreek.com/2011/07/java-equals-and-hashcode-contract/

  • 相关阅读:
    spring源码下载
    java资料共享
    《Linux命令行与shell脚本编程大全》读书笔记
    《微服务设计》读书笔记
    tornado关于AsyncHTTPClient的使用笔记
    java stackoverflowerror与outofmemoryerror区别(转)
    JAVA关于泛型的笔记
    在JAVA中返回类型使用泛型T和Object有什么区别?
    《构架师的12项修炼》读书笔记
    关于控制台输入的代码怎么跑单元测试的问题记录
  • 原文地址:https://www.cnblogs.com/chenpi/p/5489494.html
Copyright © 2011-2022 走看看