• [复习]java中hashCode的作用


    1.HashCode的官方文档定义

    (1)hashcode方法返回该对象的哈希码值。支持该方法是为哈希表提供一些优点,例如java.util.HashTable提供的哈希表。

    (2)hashCode的常规协定是:在java应用程序执行期间,在同一对象上多次调用hashcode的方法的时候,必须一致的放回相同的值,前提是对象上equals比较中所用的信息没有被修改,从某应用程序的一次执行到同一程序的另一次执行,该值无需保持一致。

    (3)如果根据equals()方法,两个对象是相等的,那么在两个对象中的每个对象调用hashcode方法都必须生成相同的值。

        如果根据 equals(java.lang.Object) 方法得到两个对象不相等,那么在两个对象中的任一对象上调用 hashCode 方法必定会生成不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的。当equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

    2.对上述文档进行总结

    (1)hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构中确定对象的存储地址的

    (2)如果两个对象相同,就是适用于equals(Java.lang.Object) 方法,那么这两个对象的hashCode一定要相同

    (3)如果对象的equals方法被重写,那么对象的hashCode也尽量重写,并且产生hashCode使用的对象,一定要和equals方法中使用的一致

    (4)两个对象的hashCode相同,并不一定表示两个对象就相同,也就是不一定适用于equals(java.lang.Object) 方法,只能够说明这两个对象在散列存储结构中,如Hashtable,他们“存放在同一个篮子里”。

    3.再来说下hashCode和equals之间有什么关系吧?

    (1)已知:hashcode是用来查找的,比如 内存中有这么几个位置0 1 2 3 4 5 6 7  8 9,我们定义了包含id属性字段的一个类,我要把类存放在以上10个位置中的一个,如果不用hashcode而任意存放,那么查找只能遍历或者二分之类的查找,这时候我们的hashcode闪亮登场。

        用一种比较简单的hash编码方法,如id字段%10取余得到的是hashcode,然后把类放在hashcode的那个位置,如id=9,9%10=9,这样类就放在9的那个位置,这样在查找的时候可以通过id%10来直接找到类存放的位置了。

    (2)两个类有相同的hashcode怎么办,如9和19得到的hashcode相同,当然我们这里不是要说hash冲突啊,会有专门的一篇将hashcode算法和冲突的,那我们该如何找到我们要找的那个类,这就是equals了,我们先用hashcode找到类放在哪里,再通过equals找到我们要找的类,所以重写equals()也要重写hashcode,因为不通过hashcode先找到那个类放在哪,光重写equals也没有意义啊

    自己举例说明下,看完你就相信这两兄弟确实关系密切啊?

    test-1

    public class testPlay {
        private int i;
    
        public int getI() {
            return i;
        }
    
        public void setI(int i) {
            this.i = i;
        }
    
        public int hashCode() {
            return i % 10;
        }
    
        public final static void main(String[] args) {
            testPlay a = new testPlay();
            testPlay b = new testPlay();
            a.setI(1);
            b.setI(1);
            Set<testPlay> set = new HashSet<>();
            set.add(a);
            set.add(b);
            System.out.println(a.hashCode() == b.hashCode());
            System.out.println(a.equals(b));
            System.out.println(set);
        }

    以上输出:

    true
    false
    [com.xrxs.waves.testPlay@1, com.xrxs.waves.testPlay@1]

      可以看书,重写了hashcode方法之后,两个对象的hashcode相等,但是两个对象不相同,那是因为我们没有重写equals方法。这样就会调用类中默认的equals方法,会比较两个对象的引用是不是相同,自然是不相同了,对于hashset来说,只能放唯一的对象,也就是相同的对象只能存放一个,所以这里我们发现确实两个对象都被放进去了。所以我们再来一次加上equals方法,看否相同。

    test-2

    public class testPlay2 {
            private int i;
    
            public int getI() {
                return i;
            }
    
            public void setI(int i) {
                this.i = i;
            }
    
            public boolean equals(Object object) {
                if (object == null) {
                    return false;
                }
                if (object == this) {
                    return true;
                }
                if (!(object instanceof testPlay2)) {
                    return false;
                }
                testPlay2 other = (testPlay2) object;
                if (other.getI() == this.getI()) {
                    return true;
                }
                return false;
            }
    
            public int hashCode() {
                return i % 10;
            }
    
            public final static void main(String[] args) {
                testPlay2 a = new testPlay2();
                testPlay2 b = new testPlay2();
                a.setI(1);
                b.setI(1);
                Set<testPlay2> set = new HashSet<>();
                set.add(a);
                set.add(b);
                System.out.println(a.hashCode() == b.hashCode());
                System.out.println(a.equals(b));
                System.out.println(set);
            }
    
    }
    

     以上输出:

    true
    true
    [com.xrxs.waves.testPlay2@1]

    我们发现两个对象相同了,hashset中也只有一个对象。所以重写hashcode请不要忘了重写equals哦

      

  • 相关阅读:
    Maven简介
    Activiti核心API
    Activiti数据库支持
    使用idea进行activiti工作流开发入门学习
    Activiti 工作流
    枚举其他用法
    枚举类的基本使用
    kotlin中抽象类
    kotlin中接口
    kotlin 类的继承
  • 原文地址:https://www.cnblogs.com/jijiji/p/6583046.html
Copyright © 2020-2023  润新知