equal和hashcode

news/2025/10/21 21:55:37/文章来源:https://www.cnblogs.com/linqr/p/19156464

equal和hashcode


目录
  • equal和hashcode
    • 核心代码示例
    • hashCode() 方法
      • 哈希码
      • 哈希码原理
    • equals()与hashcode()的联系
      • 图形展示
    • 完整的示例代码

核心代码示例

public boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) {return false;}Brand brand = (Brand) o;return Objects.equals(name, brand.name);}@Overridepublic int hashCode() {return Objects.hash(name);}

hashCode() 方法

  • hashCode() 的作用是为对象生成一个数字“指纹”(哈希码),这个“指纹”主要用于提高在基于哈希的集合(如 HashSet、HashMap)中的查找速度.

哈希码

哈希码是一个 int 类型的整数。理想情况下,相等的对象应该拥有相同的哈希码。不相等的对象,它们的哈希码最好也不同(但这不是强制要求,只是为了让性能更好)。


哈希码原理

  1. 计算哈希码: 当你要添加一个新对象(比如 new Brand("BMW"))时,HashSet 首先调用这个对象的 hashCode() 方法,得到一个数字,比如 123。
  2. 定位“桶”: HashSet 内部其实是一个数组,它用这个哈希码(123)通过一个算法计算出这个对象应该存放在数组的哪个位置(这个位置被称为“桶”或“bucket”)。
    快速判断:
  3. 比较: 如果这个“桶”是空的,说明这个对象肯定不存在,直接放进去。整个过程连一次 equals() 调用都不需要;如果这个“桶”里已经有对象了(这种情况叫“哈希冲突”),这时才需要启动 equals() 方法,让新对象和桶里的那几个对象逐一比较,看是否真的相等。

equals()与hashcode()的联系

  • Java 规定,这两个方法必须遵守一个非常重要的契约:
    如果两个对象通过 equals() 方法比较是相等的,那么调用这两个对象中任意一个对象的hashCode() 方法都必须产生相同的整数结果。
    反过来则不成立:如果两个对象的 hashCode() 相同,它们不一定 equals()(这就是哈希冲突)。
    所以在修改判断标准时,equals和hashcode要共同重写。

图形展示

graph TDsubgraph "HashSet 内部结构 (一个哈希表)"direction LRsubgraph "内部数组 (桶数组 Bucket Array)"direction TBB0["桶 0<br>Index: 0"]B1["桶 1<br>Index: 1"]B2["桶 2<br>Index: 2"]B3["桶 3<br>Index: 3"]B4["桶 4<br>Index: 4"]B5["桶 5<br>Index: 5"]B6["桶 6<br>Index: 6"]Bn["..."]endsubgraph "桶 2 中的内容 (哈希冲突)"direction TBNode1["对象: new Brand('Apple')<br>hashCode: 102"]Node2["对象: new Brand('Google')<br>hashCode: 286"]Node3["对象: new Brand('Microsoft')<br>hashCode: 470"]endsubgraph "桶 5 中的内容 (链表结构)"direction TBNode4["对象: new Brand('Ford')<br>hashCode: 789"]Node5["对象: new Brand('Audi')<br>hashCode: 789"]endsubgraph "桶 6 中的内容 (红黑树结构)"direction TBTreeRoot["(根节点)<br>new Brand('Toyota')"]TreeLeft["(左子节点)<br>new Brand('BYD')"]TreeRight["(右子节点)<br>new Brand('Honda']"]TreeRoot --> TreeLeftTreeRoot --> TreeRightendend%% --- 连接关系 ---B2 --> Node1Node1 --> Node2Node2 --> Node3B5 --> Node4Node4 --> Node5B6 --> TreeRoot%% --- 样式定义 ---classDef bucket fill:#e1f5fe,stroke:#01579b,stroke-width:2px,color:#000;classDef object fill:#fff9c4,stroke:#f57f17,stroke-width:2px,color:#000;classDef tree fill:#c8e6c9,stroke:#1b5e20,stroke-width:2px,color:#000;classDef empty fill:#f5f5f5,stroke:#9e9e9e,stroke-width:1px,stroke-dasharray: 5 5,color:#9e9e9e;class B0,B1,B3,B4,B7,Bn bucket;class B2,B5,B6 bucket;class Node1,Node2,Node3,Node4,Node5 object;class TreeRoot,TreeLeft,TreeRight tree;class B0,B1,B3,B4,B7,Bn empty;

完整的示例代码

点击查看代码
import java.util.*;
public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String line = scanner.nextLine();int n = Integer.parseInt(line);List<Car> cars = new ArrayList<>();List<Brand> brands = new ArrayList<>();for(int i=0;i<n;i++) {line = scanner.nextLine();Brand brand = new Brand(line);if(!brands.contains(brand)) {//应用brands.add(brand);cars.add(new Car(brand));}else {System.out.println(line+" exists");}}for(Car car:cars) {System.out.println(car);}System.out.println(ArrayList.class.getClassLoader());scanner.close();}
}
class Brand{private String name;public Brand(String name) {this.name = name;}public String toString() {return "Brand [name="+name+"]";}public boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) //判断相同类{return false;}Brand brand = (Brand) o;return Objects.equals(name, brand.name);}@Overridepublic int hashCode() {return Objects.hash(name);}
}
class Car{int id;Brand brand;private static int counter=0;static {System.out.println("0 car");}public Car(Brand brand) {this.brand = brand;this.id = ++counter;}public String toString() {return "Car [id="+id+"brand="+brand.toString()+"]";}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/942700.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows系统内存占用过高,且任务管理器找不到对应进程

Windows系统内存占用过高,且任务管理器找不到对应进程 现象描述 开机后系统卡顿,任务管理器查看内存占比达到90%+,统计APP实际消耗内存远小于标称占比。 解决方案cmd输入resmon打开资源监视器 按照工作集内存占用大…

NOIP 二十五

树哈希+类折半搜索+图论+最短路树A. 容易发现对于一个节点 \(u\) ,其有 \(v\) 棵子树是同构的,那么总方案数将乘上 \(v!\) 。 根节点可能也会参与这种交换,为了避免这种讨论,我们将重心设为根进行 dfs 。 当存在两…

理想婚姻

理想婚姻 # 理想婚姻 纵观我的成长经历,长辈们婚姻历史给我最多的感受是执子之手与子偕老,并风雨同舟携手共进。在种淳朴的农村婚姻思想里潜移默化的成长了。爷爷奶奶他们那一代人,风里雨里坎坎坷坷,历经了国家的各…

php如何生成6位不重复的字符串

PHP如何生成6位不重复的字符串 在Web开发中,经常需要生成不重复的随机字符串用于验证码、短链接、订单号等场景。本文将深入探讨7种PHP生成6位不重复字符串的方法,分析它们的实现原理、性能表现和适用场景。 一、需求…

「清华集训2014-主旋律」题解

题解记录P11714 [清华集训 2014] 主旋律 pref 怎么新赛季就开始了。 一直想补岁月,但至今没有实现,也就只好先从主旋律下手。我该在哪里停留?我问我自己。sol 题意就是求删后原图仍强联通的有向边删边方案数。 强联…

Hetao P5593 删 题解 [ 蓝 ] [ 线性 DP ] [ DFS 序 ] [ 虚树 ]

删:思路很新奇的一道 DP 题。 通常做树形 DP 都是自底向上进行 DP 的,而此题因为转移与 DFS 序有关,所以可以拍在 DFS 序上 DP。 观察删除的性质,发现一个点 \(u\) 要么被删掉,不进行匹配,要么就必须要与 \(\bm{…

第二次高级程序作业

2025高级语言程序设计 https://edu.cnblogs.com/campus/fzu/gjyycx/homework/13570 102500426康凯帆书本外额外的题目程序清单3.11练习题 做完这些练习题,让我对于c语言有了更深的了解,以往都是听理论模模糊糊,现在…

大学生需要认真听课的肌肉记忆(注意力训练)

原文:Scalers:大学生上课为什么一定要认真听讲? https://www.scalerstalk.com/816-attention2) 读这篇文我有很深的共鸣,以及一些困惑的解答。 原文说,认真听讲是一种能力,我在读大学一年后无比赞同。事实上不…

Ancestral Problem 题解

逆天卡常匈牙利吊打 dinic 下面默认二分图匹配的复杂度是 \(\mathcal{O}(m\sqrt n)\),其中 \(n\) 是点数,\(m\) 是边数。 暂时默认 \(m=\mathcal{O}(n)\) 因为不影响分析复杂度。首先容易写出 \(\mathcal{O}(n^{3.5}…

AWS IAM角色最佳实践:构建云安全的核心防线

本文深入探讨AWS IAM角色的核心概念与最佳实践,涵盖身份识别、权限管控、威胁检测和自动响应等关键环节,通过具体配置示例展示如何有效保护云环境安全,避免权限滥用和潜在威胁。AWS IAM角色最佳实践 Amazon Web Ser…

初始人工智能和机器学习

一、初始人工智能 1.人工智能是一个抽象的概念,它不是任何具体的机器或算法。任何类似于人的智能或高于人的智能的机器或算法都可以称为人工智能。应用:机器人等。 2.机器学习是AI系统需要具备自我学历的能力,即从原…

盒子模型外边距合并问题

两个外边距重合时,那个大用哪个 当只给子级盒子创建顶部外边距时,会连带着父级盒子一起隔离 第一种:取消子级外边距,给父级加内边距(加内边距会撑大盒子) 规避撑大盒子 2.给父级溢出的部分给隐藏 3.加细边框线显示出多…

o(N^2)找出所有回文子串

1、对于一个字符串如果(i - 1, j - 1)为回文串,并且s[i] == s[j],那么(i, j)也是一个回文串 2、双重循环,外层从大到小,内层从小到大,这样就可以由小区间推到大区间(可以写下思考一下)int vis[2010][2010];mems…

蛋白表达技术概述

一、蛋白表达的定义 蛋白表达(Protein Expression) 是指通过人工构建的基因表达系统,在特定宿主细胞中合成目标蛋白的过程。在自然界中,基因经转录和翻译形成蛋白质,这是生命活动的基本过程。在实验和工业生产中,…

二叉树的中序遍历- 递归原理 - MKT

二叉树的中序遍历- 递归原理

二叉树的中序遍历- 二叉树基本-栈 - MKT

二叉树的中序遍历- 二叉树基本-栈 前序遍历非递归实现​​:void preorderIterative(TreeNode* root) {if (root == nullptr) return;stack<TreeNode*> s;s.push(root);while (!s.empty()) {TreeNode* node = s…

二叉树的中序遍历- 二叉树基本-递归 - MKT

二叉树的中序遍历- 二叉树基本-递归 #include <iostream> #include <queue> using namespace std;struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(nullptr…

二叉树的中序遍历- 递归和栈 - MKT

二叉树的中序遍历- 递归和栈 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) …

构建YouTube视频总结摘要智能体

构建YouTube视频总结摘要智能体智能体 AI 平台 智能体 AI 框架是一个工具包,用于创建能够通过工具使用和记忆自主或半自主地推理、计划和采取行动的智能体系统。这些框架提供了创建能够与环境交互、做出决策和执行…

友链测试

// run new Vue({el: #app,data: {links: [{name: 捞月亮の小北,desc: 言念君子,温其如玉,avatar: https://youke1.picui.cn/s1/2025/10/21/68f785af89315.png,url: https://example.com},{name: Fomalhaut,desc: Fut…