【面试复盘】有了equals为什么还要hashcode

前言

早上在面一家公司的时候 被问到有了equals为什么还要hashcode方法 本来是一个比较简单的问题 但是在讲完各自的作用后想讲讲自己的理解的时候突然卡壳 所以写一篇文章来梳理一下这个逻辑

分析

首先 equals和hashcode方法通常是成对出现的 在使用一些哈希结构的时候非常重要 比如HashMap HashTable等

  • equals方法 用于判断两个对象是否相等 我们可以重写equals方法 来决定两个对象相等的逻辑 比如在String类中 重写了equals方法 认为两个字符串相等 那就是相等的
  • hashcode方法 返回一个整数哈希码 从而快速定位存储位置 提高查询效率

理解完他们的作用后 我们来看一下HashMap的源码 我这里展示了put的部分源码

ini 复制代码
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
               boolean evict) {
    Node<K,V>[] tab; Node<K,V> p; int n, i;
    if ((tab = table) == null || (n = tab.length) == 0)
        n = (tab = resize()).length;
    if ((p = tab[i = (n - 1) & hash]) == null)
        tab[i] = newNode(hash, key, value, null);
    else {
        Node<K,V> e; K k;
       //如果哈希值相等 
        if (p.hash == hash &&
        //判断地址相同 或者 逻辑相同
            ((k = p.key) == key || (key != null && key.equals(k))))
            e = p;
        else if (p instanceof TreeNode)
            e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
        else {
            for (int binCount = 0; ; ++binCount) {
                if ((e = p.next) == null) {
                    p.next = newNode(hash, key, value, null);
                    if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                        treeifyBin(tab, hash);
                    break;
                }
              //   //如果哈希值相等 
                if (e.hash == hash &&
                //地址相同 或者 逻辑相同
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    break;

通过查看源码可以发现 hashcode的计算值

  • 用于寻找插入位置 并且用于快速判断两个元素是否相同
  • 如果相同再判断两个元素是否是同一个元素

总结

总的来说

分为两方面 提高效率 保证对象唯一性

hashcode提供了一种快速计算对象哈希值的方式 可以快速定位到元素应该存放在哪 提高了查询和存放效率

另外一方面 和equals做协同 保证数据的一致性和完整性 通过HashMap的源码也可以看到 他会缓存已有键值对的哈希码 用于快速判断元素是否存在 如果两个对象的hashcode值不同 那么就不可能是同一个对象 如果相同 再通过equals判断两个对象是否相等 既保证了正确性 又提高了性能

相关推荐
大鸡腿同学几秒前
大模型是怎么训练出来的?
后端
lizhongxuan20 分钟前
判断一个人懂不懂 agent harness
后端
非洲农业不发达1 小时前
windows终端体验大升级,让你拥有macos级别的美化
前端·后端
妙码生花1 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十七):登录接口完善,登录页接口整合,解决跨域
前端·后端·ai编程
SamDeepThinking2 小时前
从源码到代码:MyBatis-Flex 与 MyBatis-Plus 的逐项对比
java·后端·程序员
shepherd1112 小时前
一文带你掌握 LLM、Token、Context、Prompt、RAG、MCP、Skill、Agent 等 AI 核心概念
人工智能·后端·ai编程
狂炫冰美式2 小时前
人均配了AI, 为什么公司还是没变快? 🤔 本质还是分布式系统问题
前端·后端·架构
她的男孩4 小时前
Spring Boot 接 Flowable 工作流:用 3 个注解搭一个请假审批流程
java·后端·架构
爱读源码的大都督5 小时前
Claude Code源码分析(三):为什么系统提示词中需要有tools呢?
前端·人工智能·后端