为什么 String#equals 方法在做比较时没有使用 hashCode

news/2024/11/18 9:40:49/

一个疑问的引入

我之前出于优化常数项时间的考虑,想当然的认为 String#equals 会事先使用 hashCode 进行过滤

我想像中的算法是这样的

  1. 当两个 hashCode 不等时,直接返回 false(对 hash 而言,相同的输入会得到相同的输出)。此时就能避免后续的双指针比对(时间复杂度: O ( m i n ( n , m ) ) O(min(n, m)) O(min(n,m)))
  2. 当两个 hashCode 相等时,考虑 hash collision(不同的输入可能会得到相同的输出)。此时后面的比对就无法避免了

也就是以下的代码

public boolean equals(Object anObject) {if (this == anObject) {return true;}if (anObject instanceof String) {String anotherString = (String)anObject;int n = value.length;if (n == anotherString.value.length && this.hashCode() == anotherString.hashCode()) {char v1[] = value;char v2[] = anotherString.value;int i = 0;while (n-- != 0) {if (v1[i] != v2[i])return false;i++;}return true;}}return false;
}

但事实上确是

public boolean equals(Object anObject) {if (this == anObject) {return true;}if (anObject instanceof String) {String anotherString = (String)anObject;int n = value.length;if (n == anotherString.value.length) {char v1[] = value;char v2[] = anotherString.value;int i = 0;while (n-- != 0) {if (v1[i] != v2[i])return false;i++;}return true;}}return false;
}

也就是我先前的设计思路有问题,但不妨参考一下 HashMap#getNode

final Node<K,V> getNode(int hash, Object key) {Node<K,V>[] tab; Node<K,V> first, e; int n; K k;if ((tab = table) != null && (n = tab.length) > 0 &&(first = tab[(n - 1) & hash]) != null) {if (first.hash == hash && // always check first node,显然这里是利用了 hashCode 进行过滤的((k = first.key) == key || (key != null && key.equals(k))))return first;if ((e = first.next) != null) {if (first instanceof TreeNode)return ((TreeNode<K,V>)first).getTreeNode(hash, key);do {if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))return e;} while ((e = e.next) != null);}}return null;
}

也就是说之前构思出来的算法应该是没有问题的,于是就有了一个疑问:为什么 String#equals 不使用 hashCode 进行第一次过滤?

一个我认为靠谱的答案

stackoverflow 高分答案

  1. String 的 hashCode 是延迟计算的,当字符串很长时进行 hash 的开销会很大(时间复杂度 O ( N ) O(N) O(N)),如果是一个生命周期很短的字符串,则代价会很大
  2. 在实际实践中,大部分的字符串一般前面的字符就会不同,所以就算挨个比较也不会比较太多(如果计算 hashCode 则需要同时计算两个字符串,那么时间复杂度就会是 O ( M + N ) O(M+N) O(M+N)

出于对第一条的解读,在 HashMap 中做为 key 存在的字符串一般周期会存在的比较长所以计算 hashCode 是一个明智的选择

结合第一、二条来看,String#euqals 使用 hashCode 就显得不是很划算了

参考资料

  • 《Why does the equals method in String not use hash?》

彩蛋

在这里插入图片描述
把 chatGPT 都忽悠瘸了


http://www.ppmy.cn/news/91898.html

相关文章

MOSN 基于延迟负载均衡算法——走得更快,期待走得更稳

文&#xff5c;纪卓志&#xff08;GitHub ID&#xff1a;jizhuozhi) 京东高级开发工程师 MOSN 项目 Committer 专注于云原生网关研发的相关工作&#xff0c;长期投入在负载均衡和流量控制领域 前言 这篇文章主要是介绍 MOSN 在 v1.5.0 中新引入的基于延迟的负载均衡算法#2…

Android HCE开发

我们来详细说明一下关于不同模式下的AID响应问题&#xff08;前提&#xff1a;一个手机&#xff0c;手机上有A、B两个HCE APP&#xff0c;通过读卡器向手机发送APDU选择指令&#xff09; 1、A和B的应用AID设置的都是payment模式&#xff0c; 只有手机当前选定的默认支付APP会响…

Kotlin 中的高阶函数及其应用

前言 前段时间一直在面试&#xff0c;某次面试&#xff0c;面试官看着我的简历说&#xff1a;“看你写的你很了解 kotlin 哦&#xff1f;那你说一说&#xff0c;为什么 kotlin 可以将函数作为参数和返回值&#xff0c;而 java 不行&#xff1f;” 我&#xff1a;“……”。 …

SQL Server数据库使用

文章目录 前言一、SQL Server 2008 R2 安装例&#xff1a;安装一台SQL Server 2008 R2服务器 二、SSMS管理工具简介1.SQL Server 2008 R2常用的工具2.连接到服务器 三、SQL Server数据库分类及管理1.SQL Server数据库分类2.SQL Server数据库文件类型3.SQL Server数据库管理例&a…

〖大学生·技术人必学的职业规划白宝书 - 优质简历篇④〗- 优质简历的撰写技巧之个人信息撰写技巧

历时18个月,采访 850+ 得到的需求。 不管你是在校大学生、研究生、还是在职的小伙伴,该专栏有你想要的职业规划、简历、面试的答案。说明:该文属于 大学生技术人职业规划白宝书 专栏,购买任意白宝书体系化专栏可加入TFS-CLUB 私域社区,早鸟价订阅模式除外。福利:加入社区…

【问题小记】解决Linux下php-fpm进程过多耗尽内存问题

最近一段时间&#xff0c;发现经常性的服务器内存耗尽&#xff0c;导致mysql服务down掉&#xff0c;一开始以为是mysql跑的太久占用较多内存&#xff0c;后来认真排查了一下原来是是PHP-FPM进程过多导致的。 今天一看内存又达到了82%&#xff0c;预计不会太久服务又会挂掉&…

面试题:什么是 TCP/IP?

目录标题 什么是 TCP/IP?1) 网络接口层:2) 网络层:3) 传输层:4) 应用层: 2.数据包3.网络接口层4.网络层1) IP:2)地址解析协议 ARP3)子网 5 传输层1&#xff09;UDP&#xff1a;2&#xff09;TCP&#xff1a; 6 应用层运行在TCP协议上的协议&#xff1a;运行在UDP协议上的协议&…

先导篇章 - 绪论

一、介绍-老师寄语 为什么选择C&#xff1f; 高性能解决问题 二、C推荐书目 1. 基础 《C Primer》&#xff0c;Stanley B. Lippman 等著&#xff0c;王刚、杨巨峰等译 2. 进阶 《Effective C》&#xff0c;Scott Meyers 著&#xff0c;侯捷译。 《More Effective C》&am…