栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

在Java中,为什么equals()和hashCode()必须一致?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在Java中,为什么equals()和hashCode()必须一致?

当然:

public class Test {  private final int m, n;  public Test(int m, int n) {    this.m = m;    this.n = n;  }  public int hashCode() { return n * m; }  public boolean equals(Object ob) {    if (ob.getClass() != Test.class) return false;    Test other = (Test)ob;    return m == other.m;  }}

与:

Set<Test> set = new HashSet<Test>();set.put(new Test(3,4));boolean b = set.contains(new Test(3, 10)); // false

从技术上讲应该是正确的,因为在两种情况下m == 3。

通常,HashMap的工作方式如下:它具有可变数量的通常称为“存储桶”的数量。存储桶的数量可以随时间变化(随着条目的添加和删除),但始终为2的幂。

假设一个给定的

HashMap
有16个存储桶。调用put()添加条目时,将计算密钥的hashCode(),然后根据存储桶的大小采用掩码。如果您(按位)将hashCode()与15(0x0F)进行与,您将获得最后4位,等于0到15之间(包括0和15)的数字:

int factor = 4;int buckets = 1 << (factor-1) - 1; // 16int mask = buckets - 1; // 15int pre = key.hashCode();int dest = pre & mask; // a number from 0 to 15 inclusive

现在,如果该存储桶中已经有一个条目,那么您将拥有一个 碰撞 。有多种处理方法,但是HashMap使用的方法(可能是最常见的方法)是存储
。具有相同被屏蔽的hashCode的所有条目都放在某种列表中。

因此,查找给定键是否已在地图中:

  1. 计算被屏蔽的哈希码;
  2. 找到合适的桶;
  3. 如果为空,则找不到密钥;
  4. 如果不为空,则循环遍历存储桶中的所有条目,检查equals()。

通过存储桶查看是线性(O(n))操作,但它位于较小的子集上。哈希码桶确定基本上是常数(O(1))。如果存储桶足够小,则通常将对HashMap的访问描述为“在O(1)附近”。

您可以对此进行一些观察。

首先,如果您有一堆全部返回42作为其哈希码的对象,a

HashMap
仍然可以工作,但它将作为昂贵的列表运行。访问将是O(n)(因为所有内容都将在同一个存储桶中,而不管存储桶的数量如何)。实际上在面试中有人问过我。

其次,回到原来的观点,如果两个对象相等(意思是a。

equals(b) == b.equals(a) ==true
)但具有不同的哈希码,
HashMap
则将(可能)查找错误的存储桶,从而导致不可预测和不确定的行为。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/437447.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号