Java:判断是否相等小记
Java:判断是否相等小结
对 Java 中的判断是否相等,即判断两数/两对象是否相等,做一个微不足道的小小小小记
== 判断
对于基本类型和引用类型 == 的效果是不同的,如下:
- 基本类型:比较的值是否相同;
- 引用类型:比较的是是否引用同一对象,即引用对象的地址值是否相等
示例:
int int_a = 10;
int int_b = 10;
System.out.println(int_a==int_b); // true
String stra = "abc";
String strb = "abc";
String strc = new String("abc"); // 通过new String()方法重新开辟了内存空间
String strd = new String("abc");
System.out.println(stra==strb); // true
System.out.println(stra==strc); // false
System.out.println(strc==strd); // false
equals 方法
equals() 方法:首先,原始的 equals 方法,只是用于比较两个对象的内存地址是否为同一个,如下:
public boolean equals(Object obj) {
return (this == obj);
}
而如果没有对 equals 方法进行重写,则比较的是引用类型的变量所指向的对象的地址(很多类重写了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等)。
如下代码所示:
// Person没有对equals方法进行重新,而String对equals方法进行了重写
private class Person{
public String name;
public Person(String name) {
this.name = name;
}
}
@Test
public void test02(){
String strc = new String("abc");
String strd = new String("abc");
System.out.println(strc.equals(strd)); // true
Person p1 = new Person("张三");
Person p2 = new Person("张三");
System.out.println(p1.equals(p2)); // false
}
查看 Person 类中的 equals 方法:本质上 equals 就是 ==,即比较两个对象地址
public boolean equals(Object obj) {
return (this == obj);
}
查看 String 类中的 equals 方法:
public boolean equals(Object anObject) {
if (this == anObject) {
return true; // 地址相同直接返回true
}
if (anObject instanceof String) { // 判断是否为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;
}
同时需要注意的是:equals 不能用于基础类型的比较,因为 equals 是一个方法,而基础类似并不是一个对象,没有对应的方法
hashCode() 方法
hashCode() 方法:
提到 hashCode,自然联想到哈希表,通过 hashCode 方法,将 key 映射到哈希表中的一个位置,从而达到最好情况下以 O(1) 的时间复杂度来查询。
// Object类的源码中,hashcode() 是一个 native 方法,哈希值的计算利用的是内存的地址
public native int hashCode();
问:为什么重写 equals() 就一定要重写 hashCode() 方法?
equals() 方法:
首先,原始的 equals 方法,只是用于比较两个对象的内存地址是否为同一个,如下:
public boolean equals(Object obj) {
return (this == obj);
}
而重写 equals() 方法,是为了实现当两个对象指向的内存地址相同或者两个对象各自字段值相同,那么标识其为同一个对象。
为什么要重写?
这个问题应该是有个前提,就是你需要用到 HashMap、HashSet 等 Java 集合,用不到哈希表的话,其实仅仅重写 equals() 方法也可以。而工作中的场景是常常用到 Java 集合,所以 Java 官方建议重写 equals() 就一定要重写 hashCode() 方法。
- 提高效率:对于对象集合的判重,如果一个集合含有 10000 个对象实例,仅仅使用
equals()方法的话,那么对于一个对象判重就需要比较 10000 次,随着集合规模的增大,时间开销是很大的。但是同时使用哈希表的话,就能快速定位到对象的大概存储位置,并且在定位到大概存储位置后,后续比较过程中,如果两个对象的 hashCode 不相同,也不再需要调用 equals() 方法,从而大大减少了 equals() 比较次数。 - 在实际应用过程中,如果仅仅重写了
equals(),而没有重写hashCode()方法,会出现什么情况?字段属性值完全相同的两个对象因为 hashCode 不同,所以在 HashMap 中的 table 数组的下标不同,从而这两个对象就会同时存在于集合中,所以重写equals()就一定要重写hashCode()方法。
hashCode() 与 equals() 的相关规定:
- 如果两个对象相等,则 hashCode 一定也是相同的;
- 两个对象相等,对两个对象分别调用 equals 方法都返回 true;
- 两个对象有相同的 hashCode 值,它们也不一定是相等的;
- equals 方法被覆盖过,则 hashCode 方法也必须被覆盖;
hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)。
对上述第3点进行说明:两个对象的 hashCode() 相同,则 equals() 不一定为 true,如下
@Test
public void test03(){
String str1 = "通话";
String str2 = "重地";
System.out.println("str1 hashCode:"+str1.hashCode()); // 1179395
System.out.println("str2 hashCode:"+str2.hashCode()); // 1179395
}
在散列表中,hashCode()相等,只是说明两个键值对的哈希值相等,但是哈希值相等,并不一定可以得出键值对相等。
参考
https://mp.weixin.qq.com/s/4E3xRXOVUQzccmP0yahlqA
https://blog.csdn.net/qq_41701956/article/details/103223461
https://blog.csdn.net/sixingmiyi39473/article/details/78306296
Java:判断是否相等小记的更多相关文章
- Java:ConcurrentHashMap类小记-3(JDK8)
Java:ConcurrentHashMap类小记-3(JDK8) 结构说明 // 所有数据都存在table中, 只有当第一次插入时才会被加载,扩容时总是以2的倍数进行 transient volat ...
- Java:ConcurrentHashMap类小记-2(JDK7)
Java:ConcurrentHashMap类小记-2(JDK7) 对 Java 中的 ConcurrentHashMap类,做一个微不足道的小小小小记,分三篇博客: Java:ConcurrentH ...
- Java:HashMap类小记
Java:HashMap类小记 对 Java 中的 HashMap类,做一个微不足道的小小小小记 概述 HashMap:存储数据采用的哈希表结构,元素的存取顺序不能保证一致.由于要保证键的唯一.不重复 ...
- Java:HashTable类小记
Java:HashTable类小记 对 Java 中的 HashTable类,做一个微不足道的小小小小记 概述 public class Hashtable<K,V> extends Di ...
- Java:LinkedList类小记
Java:LinkedList类小记 对 Java 中的 LinkedList类,做一个微不足道的小小小小记 概述 java.util.LinkedList 集合数据存储的结构是循环双向链表结构.方便 ...
- Java:ArrayList类小记
Java:ArrayList类小记 对 Java 中的 ArrayList类,做一个微不足道的小小小小记 概述 java.util.ArrayList 是大小可变的数组的实现,存储在内的数据称为元素. ...
- Java:动态代理小记
Java:动态代理小记 对 Java 中的 动态代理,做一个微不足道的小小小小记 概述 动态代理:当想要给实现了某个接口的类中的方法,加一些额外的处理.比如说加日志,加事务等.可以给这个类创建一个代理 ...
- 使用Java判断字符串中的中文字符数量
Java判断一个字符串str中中文的个数,经过总结,有以下几种方法(全部经过验证),可根据其原理判断在何种情况下使用哪个方法: 1. char[] c = str.toCharArray(); for ...
- Java判断回文数算法简单实现
好久没写java的代码了, 今天闲来无事写段java的代码,算是为新的一年磨磨刀,开个头,算法是Java判断回文数算法简单实现,基本思想是利用字符串对应位置比较,如果所有可能位置都满足要求,则输入的是 ...
- Java 判断操作系统类型(适用于各种操作系统)
Java 判断操作系统类型(适用于各种操作系统) 最近一段时间写一个授权的程序,需要获取很多信息来保证程序不能随意复制使用,必须经过授权才可以. 为了限制用户使用的操作系统,必须有统一的方法来获取才可 ...
随机推荐
- RDS导入注意事项
1)导入文件大小不超过100M,支持格式有CSV.SQL.ZIP 2)sql文件需注释如下内容: SET @@SESSION.SQL_LOG_BIN=0 ; SET @@GLOBAL.GTID_PUR ...
- 这篇 Java 基础,我吹不动了
Hey guys,这里是程序员cxuan,欢迎你收看我最新一期的文章,这篇文章我补充了一些关于<Java基础核心总结>的内容,修改了部分错别字和语句不通顺的地方,并且对内部类.泛型等内容进 ...
- .Net 如何修改 HttpHeaders 中的 Content-Disposition
最近在看一些.Net5的内容,于是就想将之前Spring写的一个项目迁移到.Net上来看看. 不得不说.Net这几年发展的确实挺好的,超快的启动速度,极佳的性能让它一点不比Java差,但确实在国内生态 ...
- TCL、华星光电和中环股份,如何在一条生态链上领跑?
聚众智.汇众力.采众长. "我们决心用五年时间,将TCL科技和TCL实业做到真正的世界500强,将智能终端.半导体显示.半导体光伏三大核心产业力争做到全球领先,将半导体材料等其他产业做到中国 ...
- ClickOnce手动更新
if (ApplicationDeployment.IsNetworkDeployed == true) { ApplicationDeploy ...
- ssh跳转设置
SSH工具的非常规使用 原创 景朝阳 FreeSWITCH中文社区 今天 说明:本文所有的命令是基于OpenSSH客户端7.4p1版本.如果出现命令不正确,请检测是否为此OpenSSH版本. 设置 ...
- vue 工作随笔
现在工作要做一个电商项目,将工3作的笔记记在这儿,以后方便结总 本套项目用的前端方案 是: vue vue-router Element -ui Axios Echarts 后端技术采用node.js ...
- 洛谷P1088——火星人(全排列+数学模拟)
题目描述 人类终于登上了火星的土地并且见到了神秘的火星人.人类和火星人都无法理解对方的语言,但是我们的科学家发明了一种用数字交流的方法.这种交流方法是这样的,首先,火星人把一个非常大的数字告诉人类科学 ...
- 《Android自动化环境搭建》
一.安装JDK并配置环境变量 1:在Java官网上下载本机系统相对应的jdk文件安装,直接下一步一步到位 2:配置JAVA_HOME 新建 JAVA_HOME 环境变量,变量值是所安装JDK 的路径, ...
- 牛客练习赛84F-牛客推荐系统开发之下班【莫比乌斯反演,杜教筛】
正题 题目链接:https://ac.nowcoder.com/acm/contest/11174/F 题目大意 给出\(n,k\)求 \[\sum_{i_1=1}^n\sum_{i_2=1}^n.. ...