zoukankan      html  css  js  c++  java
  • 为什么重写equals方法一定要重写hashcode方法

    为什么重写equals方法一定要重写hashcode方法

    • equals() 定义在JDK的Object.java中。通过判断两个对象的地址是否相等(即,是否是同一个对象)来区分它们是否相等
    • hashCode()的作用是获取散列码
    • 如果不使用HashTable,”hashCode() 和 equals() ”没有关系的!

    HashSet、hashcoede()、equals()之间的关系

    • 用到散列表时,”hashCode() 和 equals() ”是有关系的!

      例如:
      HashSet的add其实是Hashmap的put方法,key为添加值,value是一个final固定值。
      Hashmap的插入key的判断顺序是:先判断hashcode(找到),不相同则插入;相同则继续比较equals是否为true,如果为true则表示两个对象相等,不能插入;如果是false(哈希冲突)则会散列到其他位置(头插)。

    • 第一步首先将k,v封装到Node对象当中(节点)。
    • 第二步它的底层会调用K的hashCode()方法得出hash值。
    • 第三步通过哈希表函数/哈希算法,将hash值转换成数组的下标,下标位置上如果没有任何元素,就把Node添加到这个位置上。如果说下标对应的位置上有链表。此时,就会拿着k和链表上每个节点的k进行equal。如果所有的equals方法返回都是false,那么这个新的节点将被添加到链表的末尾。如其中有一个equals返回了true,那么这个节点的value将会被覆盖。
    1. 两个对象相等,equals为true
    2. 两个对象相等,hashcode一定相同(根据属性计算而来,相等的对象属性一定相等)
    3. equals为true、hashcode一定相同
    4. 相同的hashcode,对象不一定相等(equals不一定为true)

    总结:

    • equals=true =》hashcode()相同 、反之不行

    • 如果要使用散列表并且重写了equals方法就一定要重写hashcode()方法,以保证相同的对象不能同时加入HashSet中。

    为什么重写equals方法一定要重写hashcode方法?

    先看String类重写的这两个方法

    public boolean equals(Object anObject) {
    		//判断地址是否一样、一样则直接返回
            if (this == anObject) {
                return true;
            }
            //判断对象是否属于String类
            if (anObject instanceof String) {
            	//开始比较
                String anotherString = (String)anObject;
                int n = value.length;
                if (n == anotherString.value.length) {
                    char v1[] = value;
                    char v2[] = anotherString.value;
                    int i = 0;
                    while (n-- != 0) {
                        if (v1[i] != v2[i])
                            return false;
                        i++;
                    }
                    return true;
                }
            }
            return false;
        }
    
    
    public int hashCode() {
    		//进行hash计算
            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;
        }
    

    现在来看自己写的类
    1、先看自动生成的者两个方法
    默认生成的比较了book类的所有参数,以及进行了哈希运算。

    class Book1 {
        int id;
        String name;
        String author;
        double price;
        /**
         * 重写equals方法比较id和name
         * @param o
         * @return
         */
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Book1 book1 = (Book1) o;
            return id == book1.id &&
                    Double.compare(book1.price, price) == 0 &&
                    Objects.equals(name, book1.name) &&
                    Objects.equals(author, book1.author);
        }
         /**
         * 重写equals要重写hashcode  set加入时会先判断hashcode是否相等,再判断是否equals
         * 只有hashcode相同 和equals 同时成立  才能保证set的所有元素都不相等
         * @return
         */
        @Override
        public int hashCode() {
    
            return Objects.hash(id, name, author, price);
        }
    }
    

    如果只是改写了equals方法 。hashcode()调用的而是本地方法,每个对象都有自己的hashcode

    public native int hashCode();
    

    这样的话我们定义的两个相同(equals为true)的对象都能成功加入hashset,所以必须同时覆盖这两个方法。

     Book1 b1 = new Book1(1, "hh", "zs", 122.0);
     Book1 b2 = new Book1(1, "hh", "zh", 112.0);
    

    改写后、这两个对象hashcode相同,equals,所以只能加进去一个到HashSet中

  • 相关阅读:
    完全背包笔记
    渗透测试之信息收集常用网站
    结对项目-四则运算"软件"之升级版
    第三次作业:个人项目-小学四则运算“软件”之初版
    分布式版本控制系统Git的安装与使用
    第一次作业:准备
    爬虫综合大作业
    爬取全部校园新闻
    理解爬虫原理
    中文词频统计与词云生成
  • 原文地址:https://www.cnblogs.com/jklixin/p/13455727.html
Copyright © 2011-2022 走看看