八股文 | hashcode与equals

Java中的hashcode方法

哈希表(也叫散列表)是一种常用的数据结构,通常被用来提高查找效率。无论哈希表总中有多少条数据,插入和查找的时间复杂度都是为O(1)。

//object 方法 public native int hashCode();

根据这个方法的声明可知,该方法返回一个int类型的数值,并且是(native)本地方法,因此在Object类中并没有给出具体的实现。

实际上哈希函数就是从键值到索引的过程,需要通过哈希函数来进行计算。

一. hashCode方法的作用

hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括HashSet、HashMap以及HashTable。

Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值。

//java.util.HashMap的中put方法 public V put(K key, V value) { if (key == null) return putForNullKey(value); //当集合要添加新的对象时,先调用这个对象的hashCode方法,得到对应的hashcode值 int hash = hash(key.hashCode()); //用一个table保存已经存进去的对象的hashcode值 int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; //如果存在,则更新value值 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; //将新的元素添加到HashMap中 addEntry(hash, key, value, i); return null; }

hashCode方法的存在是为了减少equals方法的调用次数,从而提高程序效率。

二. equals方法和hashCode方法

对于两个对象,如果调用equals方法得到的结果为true,则两个对象的hashcode值必定相等;

如果equals方法得到的结果为false,则两个对象的hashcode值不一定不同;

如果两个对象的hashcode值不等,则equals方法得到的结果必定为false;

如果两个对象的hashcode值相等,则equals方法得到的结果未知。

import java.util.HashMap; class People{ private String name; private int age; public People(String name,int age) { this.name = name; this.age = age; } public void setAge(int age){ this.age = age; } @Override public boolean equals(Object obj) { // TODO Auto-generated method stub return this.name.equals(((People)obj).name) && this.age== ((People)obj).age; } // @Override // public int hashCode() { // // TODO Auto-generated method stub // return name.hashCode()*37+age; // } } public class Main { public static void main(String[] args) { People p1 = new People("Jack", 12); System.out.println(p1.hashCode()); HashMap<People, Integer> hashMap = new HashMap<People, Integer>(); hashMap.put(p1, 1); System.out.println(hashMap.get(new People("Jack", 12))); } }

输出结果:

原因:

默认情况下,hashCode方法是将对象的存储地址进行映射。

p1指向的对象和 System.out.println(hashMap.get(new People("Jack", 12)));这句中的new People("Jack", 12)生成的是两个对象,它们的存储地址肯定不同。

//HashMap的get方法的具体实现: public V get(Object key) { if (key == null) return getForNullKey(); int hash = hash(key.hashCode()); for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) return e.value; } return null; }

所以,在重写equals方法的同时,必须重写hashCode方法

  • 在程序执行期间,只要equals方法的比较操作用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法必须始终如一地返回同一个整数。
  • 如果两个对象根据equals方法比较是相等的,那么调用两个对象的hashCode方法必须返回相同的整数结果。
  • 如果两个对象根据equals方法比较是不等的,则hashCode方法不一定得返回不同的整数。
  • 设计hashCode方法和equals方法的时候,如果对象中的数据易变,则最好在equals方法和hashCode方法中不要依赖于该字段。

__EOF__

本文作者张吱吱
本文链接https://www.cnblogs.com/zhangzizi/p/16053560.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   张吱吱  阅读(104)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示