为什么重写equals就必须重写hashCode

为什么重写equals就必须重写hashCode
如果不被重写原生Object的hashCode和equals是什么样的不被重写原生的hashCode值是根据内存地址换算出来的一个值。不被重写原生的equals方法是严格判断一个对象是否相等的方法object1 object2。为什么需要重写equals和hashCode方法在我们的业务系统中判断对象时有时候需要的不是一种严格意义上的相等而是一种业务上的对象相等。在这种情况下原生的equals方法就不能满足我们的需求了所以这个时候我们需要重写equals方法来满足我们的业务系统上的需求。那么为什么在重写equals方法的时候需要重写hashCode方法呢我们先来看一下Object.hashCode的通用约定摘自《Effective Java》第45页在一个应用程序执行期间如果一个对象的equals方法做比较所用到的信息没有被修改的话那么对该对象调用hashCode方法多次它必须始终如一地返回 同一个整数。在同一个应用程序的多次执行过程中这个整数可以不同即这个应用程序这次执行返回的整数与下一次执行返回的整数可以不一致。如果两个对象根据equals(Object)方法是相等的那么调用这两个对象中任一个对象的hashCode方法必须产生同样的整数结果。如果两个对象根据equals(Object)方法是不相等的那么调用这两个对象中任一个对象的hashCode方法不要求必须产生不同的整数结果。然而程序员应该意识到这样的事实对于不相等的对象产生截然不同的整数结果有可能提高散列表hash table的性能。如果只重写了equals方法而没有重写hashCode方法的话则会违反约定的第二条相等的对象必须具有相等的散列码hashCode 同时对于HashSet和HashMap这些基于散列值hash实现的类。HashMap的底层处理机制是以数组的方法保存放入的数据的(NodeK,V[] table)其中的关键是数组下标的处理数组的下标是根据传入的元素hashCode方法的返回值再和特定的值异或决定的。如果该数组位置上已经有放入的值了且传入的键值相等则不处理若不相等则覆盖原来的值如果数组位置没有条目则插入并加入到相应的链表中。检查键是否存在也是根据hashCode值来确定的。所以如果不重写hashCode的话可能导致HashSet、HashMap不能正常的运作。如果我们将某个自定义对象存到HashMap或者HashSet及其类似实现类中的时候如果该对象的属性参与了hashCode的计算那么就不能修改该对象参数hashCode计算的属性了有可能会移除不了元素导致内存泄漏。接着来看一个代码片段运行这段代码发现结果返回的是null。再来看一下HashMap中的get源码get的时候会先比较hashCode然后再去比较equals 返回结果为null其实都是hashCode惹的祸。以Java.lang.Object来理解 JVM每次new一个Object 都会将Object丢到一个哈希表中去 这样的话下次做Object的比较或者取这个对象的时候 它会根据对象的hashcode再从Hash表中取这个对象。这样做的目的是提高取对象的效率。1.new Object(),JVM根据这个对象的Hashcode值,放入到对应的Hash表对应的Key上,如果不同的对象确产生了相同的hash值,也就是发生了Hash key相同导致冲突的情况,那么就在这个Hash key的地方产生一个链表,将所有产生相同hashcode的对象放到这个单链表上去,串在一起。2.比较两个对象的时候,首先根据他们的hashcode去hash表中找他的对象,当两个对象的hashcode相同,那么就是说他们这两个对象放在Hash表中的同一个key上,那么他们一定在这个key上的链表上。那么此时就只能根据Object的equal方法来比较这个对象是否equal。当两个对象的hashcode不同的话肯定他们不能equals.以下是关于hashcode的一些规定结合hashmap的原理考虑记忆两个对象相等hashcode一定相等两个对象不等hashcode不一定不等hashcode相等两个对象不一定相等hashcode不等两个对象一定不等如果两个对象相同即equals返回true hashcode一定相等但是hashcod相等时两个对象却不一定equals 2、由于为了提高程序的执行效率才实现了hashcode方法先进行hashcode比较如果不同就没有必要进行equals比较了这样就大大的减少了equals的使用次数从而效率得到提高如果只重写hashcode()不重写equals()方法当比较equals()时只是看他们是否为同一对象即进行内存地址的比较,所以必定要两个方法一起重写。因为在 HashMap 的链表结构中遍历判断的时候特定情况下重写的 equals 方法比较对象是否相等的业务逻辑比较复杂循环下来更是影响查找效率。所以这里把 hashcode 的判断放在前面只要 hashcode 不相等就玩儿完不用再去调用复杂的 equals 了。很多程度地提升 HashMap 的使用效率。所以重写 hashcode 方法是为了让我们能够正常使用 HashMap 等集合类因为 HashMap 判断对象是否相等既要比较 hashcode 又要使用 equals 比较。而这样的实现是为了提高 HashMap 的效率当我们重写一个类的 equals 方法时就应当连同重写 hashcode 方法并且两个方法应满足1一致性即当两个对象 equals 比较为 true那么 hashcode 值应当相等反之亦然因为当两个对象hashcode 值相等但是 equals 比较为 false那么在 HashMap 中会产生链表影响查询性能。2成对重写即重写 equals 就应当重写 hashcode。参考文章:https://www.cnblogs.com/wang-meng/p/7501378.htmlhttps://www.jianshu.com/p/0e1176a9bad1https://www.cnblogs.com/happyPawpaw/p/3744971.htmlhttps://www.cnblogs.com/zcjyzh/p/9329346.html