-
2021-12-18 13:17:42
Java
中的hash
值主要是用来在散列存储结构中确定对象的存储地址的,提高对象的查询效率。Java
设计的顶级父类Object
类中,有两个方法很特殊,它们分别是equals
方法与hashCode
方法。——一旦重写了equals
方法,就一定要重写hashCode
方法。以下是Object
的源码:public class Object { /* * Note that it is generally necessary to override the {@code hashCode} * method whenever this method is overridden, so as to maintain the * general contract for the {@code hashCode} method, which states * that equal objects must have equal hash codes. */ public boolean equals(Object obj) { return (this == obj); } /* * The general contract of {@code hashCode} is: * <ul> * <li>Whenever it is invoked on the same object more than once during * an execution of a Java application, the {@code hashCode} method * must consistently return the same integer, provided no information * used in {@code equals} comparisons on the object is modified. * This integer need not remain consistent from one execution of an * application to another execution of the same application. * <li>If two objects are equal according to the {@code equals(Object)} * method, then calling the {@code hashCode} method on each of * the two objects must produce the same integer result. * <li>It is <em>not</em> required that if two objects are unequal * according to the {@link java.lang.Object#equals(java.lang.Object)} * method, then calling the {@code hashCode} method on each of the * two objects must produce distinct integer results. However, the * programmer should be aware that producing distinct integer results * for unequal objects may improve the performance of hash tables. * </ul> * <p> * As much as is reasonably practical, the hashCode method defined by * class {@code Object} does return distinct integers for distinct * objects. (This is typically implemented by converting the internal * address of the object into an integer, but this implementation * technique is not required by the * Java™ programming language.) * */ public int hashCode() { return identityHashCode(this); } /* package-private */ static int identityHashCode(Object obj) { int lockWord = obj.shadow$_monitor_; final int lockWordStateMask = 0xC0000000; // Top 2 bits. final int lockWordStateHash = 0x80000000; // Top 2 bits are value 2 (kStateHash). final int lockWordHashMask = 0x0FFFFFFF; // Low 28 bits. if ((lockWord & lockWordStateMask) == lockWordStateHash) { return lockWord & lockWordHashMask; } return identityHashCodeNative(obj); } }
如果一个类没有重写
equals(Object obj)
方法,则等价于通过==
比较两个对象,即比较的是对象在内存中的空间地址是否相等;如果重写了equals(Object obj)
方法,则根据重写的方法内容去比较相等,返回true
则相等,false
则不相等。equals
方法注释中的大致意思是:当我们将equals
方法重写后有必要将hashCode
方法也重写,这样做才能保证不违背hashCode
方法中“相同对象必须有相同哈希值”的约定。hashCode
方法本质就是一个哈希函数,Object
类的作者在注释的最后一段的括号中写道:将对象的地址值映为integer
类型的哈希值。提到
hashCode
,就会想到哈希表,将某一对象的值映射到表中的某个位置,从而达到以O(1)
的时间复杂度来查询该对象的值。hashCode
是一个native
方法,哈希值的计算利用的内存地址。哈希表在一定程度上也可以起到判重的作用,但也可能存储哈希冲突,即使是两个不同的对象,它们的哈希值也可能是相同的。因此,虽然哈希表具有优越的查询性能,但也可能存在哈希冲突。hashCode
方法注释中列了个列表,列表中有三条注释,当前需要理解的大致意思如下:- 一个对象多次调用它的
hashCode
方法,应当返回相同的integer
(哈希值); - 两个对象如果通过
equals
方法判定为相等,那么就应当返回相同integer
。 - 两个地址值不相等的对象调用
hashCode
方法不要求返回不相等的integer
,但是要求拥有两个不相等integer
的对象必须是不同对象。
图中存在两种独立的情况:
- 相同的对象必然导致相同的哈希值;
- 不同的哈希值必然是由不同对象导致的;
因此,
equals
方法与hashCode
方法根本就是配套使用的。对于任何一个对象,不论是使用继承自Object
的equals
方法还是重写equals
方法。hashCode
方法实际上必须要完成的一件事情就是,为该equals
方法认定为相同的对象返回相同的哈希值。如果只重写equals
方法没有重写hashCode
方法,就会导致``equals`认定相同的对象却拥有不同的哈希值。Object
类中的equals
方法区分两个对象的做法是比较地址值,即使用==
。如果根据业务需求改写了equals
方法的实现,那么也应当同时改写hashCode
方法的实现。否则hashCode
方法依然返回的是依据Object
类中的依据地址值得到的integer
哈希值。代入到具体的例子 –
String
类,在String
类中,equals
方法经过重写,具体实现源码如下:public final class String implements java.io.Serializable, Comparable<String>, CharSequence { public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String) anObject; int n = length(); if (n == anotherString.length()) { int i = 0; while (n-- != 0) { if (charAt(i) != anotherString.charAt(i)) return false; i++; } return true; } } return false; } }
通过源码可以看到,
String
对象在调用equals
方法比较另一个对象时,除了认定相同地址值的两个对象相等以外,还认定对应着的每个字符都相等的两个String
对象也相等,即使这两个String
对象的地址值不同(即属于两个对象)。String
类中对equals
方法进行重写扩充了,但是如果此时我们不将hashCode
方法也进行重写,那么String
类调用的就是来自顶级父类Obejct
类中的hashCode
方法。即,对于两个字符串对象,使用它们各自的地址值映射为哈希值。 也就是会出现如下情形:也就是说,被
String
类中的equals
方法认定为相等的两个对象拥有两个不同的哈希值——因为它们的地址值不同。为什么重写
equals
方法就得重写hashCode
方法?—— 因为必须保证重写后的equals
方法认定相同的两个对象拥有相同的哈希值。同时我们也得出了——hashCode
方法的重写原则就是保证equals
方法认定为相同的两个对象拥有相同的哈希值。equals
里一般比较的比较全面比较复杂,这样效率就比较低,而利用hashCode
进行对比,则只要生成一个hash
值进行比较就可以了,效率很高,那么既然hashCode
效率这么高为什么还要使用equals
进行比较呢?因为
hashCode
并不是完全可靠,有时候不同的对象生成的hashcode
也会一样(hash
冲突),所以hashCode
只能说是大部分时候可靠,并不是绝对可靠。 所以可以得出:equals
相等的两个对象,它们的hashCode
肯定相等,也就是用equals
对比是绝对可靠的;hashCode
相等的两个对象,它们的equals
不一定相等,也就是hashCode
不是绝对可靠的;
所有对于需要大量并且快速的对比的话如果都用
equals
去做显然效率太低,解决方式是,每当需要对比的时候,hashCode
去对比,这就用到了哈希表,能够快速的地位到对象的存储位置,如果hashCode
不一样,则表示这两个对象肯定不相等(也就是不必再用equals
去再对比了),如果hashCode
相同,此时再对比它们的equals
,如果equals
也相同,则表示这两个对象是真的相同了。查看字符串的
hashCode
:String str = new String("abc"); System.out.println(str.hashCode()); // 96354 str += "a"; System.out.println(str.hashCode()); // 2987071 str += "b"; System.out.println(str.hashCode()); // 92599299 String str1 = "abcab"; System.out.println(str.hashCode() + " " + str1.hashCode()); // 92599299 92599299 String str2 = "ab"; String str3 = new String("ab"); System.out.println(str2.hashCode() + " " + str3.hashCode()); // 3105 3105
以下是
String.hashCode
的源码:public final class String implements java.io.Serializable, Comparable<String>, CharSequence { private int hash; // Default to 0 /** * Returns a hash code for this string. The hash code for a * {@code String} object is computed as * <blockquote><pre> * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] * </pre></blockquote> * using {@code int} arithmetic, where {@code s[i]} is the * <i>i</i>th character of the string, {@code n} is the length of * the string, and {@code ^} indicates exponentiation. * (The hash value of the empty string is zero.) * * @return a hash code value for this object. */ public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; } }
由上面的代码可知,
String
类的hashCode
的值为s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
,其中s
是字符串对应的char
数组,所以字符串内容一样的String
对象,调用hasCode()
返回值是一样的。但是反过来,当hashCode
返回的值一样时,其字符串内容不一定一样,因为上面的方法计算hash
时可能会发生位数溢出。参考
https://zhuanlan.zhihu.com/p/50206657
https://blog.csdn.net/weixin_64735186/article/details/122727751更多相关内容 - 一个对象多次调用它的
-
重写equals方法
2022-05-05 17:09:07重写equals方法 总结 我们在java程序中调用自带的equals方法时,你是否会有这样的疑问:明明我比较的数据都一样啊,为什么会返回false呢?有些人可能还会疑问,怎么有时候返回true?有时候返回false呢?这是为什么...目录
我们在java程序中调用自带的equals方法时,你是否会有这样的疑问:明明我比较的数据都一样啊,为什么会返回false呢?有些人可能还会疑问,怎么有时候返回true?有时候返回false呢?这是为什么呢?其实是和Java底层人家写的equals方法逻辑有关系
equals()方法是做什么的?
英语角度:
计算机角度:比较多个值是否相等
实战场景
先来看段代码我们脑海中有个场景吧!
User类
package StringEquals; public class User { private String name; public User() { } public User(String name) { this.name = name; } }
主函数
package StringEquals; import java.util.ArrayList; import java.util.Collection; public class Main { public static void main(String[] args) { //实例化一个集合对象 Collection c = new ArrayList(); //实例化一个叫唐三的对象 User tangsan1 = new User("唐三"); //再次实例化一个叫唐三的对象 User tangsan2 = new User("唐三"); //把第一个tangsan1对象添加到集合中 c.add(tangsan1); //判断集合中是否包含叫唐三的对象 System.out.println(c.contains(tangsan2)); } }
客户端输出结果
此时是不是就疑惑了,明明tangsan1和tangsan2这两个变量所指向的对象都叫唐三啊,集合中也有叫唐三的这个对象,那为什么在判断集合是否包含叫唐三的对象时返回false呢?这是为什么? 我们先来看看Java中底层定义的contains方法是如何进行逻辑判断的,如下图。
contains底层逻辑判断
通过进入到contains方法底层,发现在进行逻辑判断的时候会调用equals方法进行比较。我们通过debug单步调试进入到equals底层之后发现,如下图:
this==obj,这里实际上比较的是tangsan1和tangsan2这两个对象的内存地址,因为实例化时分别new了两个不同的User对象,所有tangsan1和tangsan2这两个变量实际上所存储的地址空间不同、指向的对象也不同。
内存图
我们在来画一张这个程序的内存图,看看每一个变量和对象再内存中是如何划分的,如下图:
看出来有什么不同了吗?虽然在代码中tangsan1和tangsan2这两个变量所指向的对象都叫唐三,但是他们分别所指向的对象不同,这两个对象所指向的地址也不同。
重写equals方法
有些人可能就问了,我只想判断两个对象里面的数据是否相同,如何做?重写equals方法,代码如下:
User类
package StringEquals; public class User { private String name; public User() { } public User(String name) { this.name = name; } //重写equals方法,比较连个对象里面的数据是否一致 public boolean equals(Object o) { if (o == null || !(o instanceof User)) return false; if (o == this) return true; User u = (User) o; return u.name.equals(this.name); } }
主函数
package StringEquals; import java.util.ArrayList; import java.util.Collection; public class Main { public static void main(String[] args) { //实例化一个集合对象 Collection c = new ArrayList(); //实例化一个叫唐三的对象 User tangsan1 = new User("唐三"); //再次实例化一个叫唐三的对象 User tangsan2 = new User("唐三"); //把第一个tangsan1对象添加到集合中 c.add(tangsan1); //判断集合中是否包含叫唐三的对象 System.out.println(c.contains(tangsan2)); } }
客户端输出结果
这里我们重写了equals方法,之后在调用equals方法的时候,程序就会调用我们自己写的这个重写之后的equals方法,程序就会认为tangsan1也叫唐三,tangsan2也叫唐三,他们名字相同就是同一个人。
总结
- 不重写:调用Objcet的equals方法,判断的是内存地址是否一致
- 重写:调用自定义的equals方法,判断是内容是否一致
- 存放在一个集合中的类型,一定要重写equals方法
-
【Java基础】重写equals方法详讲
2022-05-08 19:30:23重写equals方法 【Java比较学习】重写equals方法的安全写法 重写equals方法的两种方式 这里提供两个比较常见的equals重写方法: ● 用instanceof实现重写equals方法 ● 用getClass实现重写equals方法 先说结论,...一、重写equals方法
1、重写equals方法的两种方式
这里提供两个比较常见的equals重写方法:
● 用instanceof实现重写equals方法
● 用getClass实现重写equals方法先说结论,
getClass()比instanceof更安全
。接下来就是我们自己要来实现equals方法了。2、场景描述
假设有此场景:
在已经创建好的长方形类中重写Object类中的equals方法为当长方形的长和宽相等时,返回TRUE,同时重写hashCode方法,重写toString方法为显示长方形的长宽信息。并测试类。package com.test10_04; import java.util.Objects; class Rectangle { private double length; private double wide; public Rectangle() { //空实现 } public Rectangle(double length, double wide) { setLength(length); setWide(wide); } public double getLength() { return length; } public void setLength(double length) { assert length > 0.0 : "您的输入有误,长方形的长不能小于0"; this.length = length; } public double getWide() { return wide; } public void setWide(double wide) { assert wide > 0.0 : "您的输入有误,长方形的宽不能小于0"; this.wide = wide; } public double area() { return this.length * this.wide; } public double circumference() { return 2 * (this.wide + this.length); } public boolean equals(Object obj) { if (this == obj) { //判断一下如果是同一个对象直接返回true,提高效率 return true; } if (obj == null || obj.getClass() != this.getClass()) { //如果传进来的对象为null或者二者为不同类,直接返回false return false; } //也可以以下方法: // if (obj == null || !(obj instanceof Rectangle)) { //如果传进来的对象为null或者二者为不同类,直接返回false // return false; // } Rectangle rectangle = (Rectangle) obj; //向下转型 //比较长宽是否相等,注意:浮点数的比较不能简单地用==,会有精度的误差,用Math.abs或者Double.compare return Double.compare(rectangle.length, length) == 0 && Double.compare(rectangle.wide, wide) == 0; } public int hashCode() { //重写equals的同时也要重写hashCode,因为同一对象的hashCode永远相等 return Objects.hash(length, wide); //调用Objects类,这是Object类的子类 } public String toString() { return "Rectangle{" + "length=" + length + ", wide=" + wide + '}'; } } public class TestDemo { public static void main(String[] args) { Rectangle rectangle1 = new Rectangle(3.0, 2.0); Rectangle rectangle2 = new Rectangle(3.0, 2.0); System.out.println(rectangle1.equals(rectangle2)); System.out.println("rectangle1哈希码:" + rectangle1.hashCode() + "\nrectangle2哈希码:" + rectangle2.hashCode()); System.out.println("toString打印信息:" + rectangle1.toString()); } }
3、getClass和instanceof优缺点
具体实现思路在代码中讲的很清楚了,我们这里重点分析一下getClass和instanceof两种实现方法的优缺点:
将代码逻辑简化一下:
我们就重点看这段简单的代码//getClass()版本 public class Student { private String name; public void setName(String name) { this.name = name; } @Override public boolean equals(Object object){ if (object == this) return true; // 使用getClass()判断对象是否属于该类 if (object == null || object.getClass() != getClass()) return false; Student student = (Student)object; return name != null && name.equals(student.name); }
事实上两种方案都是有效的,区别就是getClass()限制了对象只能是同一个类,而instanceof却允许对象是同一个类或其子类,这样equals方法就变成了父类与子类也可进行equals操作了,这时候如果子类重定义了equals方法,那么就可能变成父类对象equlas子类对象为true,但是子类对象equlas父类对象就为false了,如下所示:
class GoodStudent extends Student { @Override public boolean equals(Object object) { return false; } public static void main(String[] args) { GoodStudent son = new GoodStudent(); Student father = new Student(); son.setName("test"); father.setName("test"); // 当使用instance of时 System.out.println(son.equals(father)); // 这里为false System.out.println(father.equals(son)); // 这里为true // 当使用getClass()时 System.out.println(son.equals(father)); // 这里为false System.out.println(father.equals(son)); // 这里为false } }
注意看这里用的是getClass()
返回值两个都是false,符合我们的预期,(连类都不一样那肯定得为false啊)
而换成instanceof试试看咯:
运行结果:一个为true一个为false,很明显出现问题了。
这里的原因如下:
instanceof的语法是这样的:
当一个对象为一个类的实例时,结果才为true。但它还有一个特点就是,如果当这个对象是其子类的实例时,结果也会为true。这便导致了上述的bug。也就是说当比较的两个对象,他们的类是父子关系时,instanceof可能会出现问题。需要深究的小伙伴可以自己去了解一哈,所以在这里建议在实现重写equals方法时,尽量使用getClass来实现。
在重写equals方法的同时需要重写hashCode方法,具体原因可能后续会讲到~~4、instanceof和getClass总结
区别就是getClass()限制了对象只能是同一个类,而instanceof却允许对象是同一个类或其子类,
5、instanceof实战
public class GenericTest01 { public static void main(String[] args) { // 使用JDK5之后的泛型机制 // 使用泛型List<Animal>之后,表示List集合中只允许存储Animal类型的数据。 // 用泛型来指定集合中存储的数据类型。 List<Animal> myList = new ArrayList<Animal>(); // 指定List集合中只能存储Animal,那么存储String就编译报错了。 // 这样用了泛型之后,集合中元素的数据类型更加统一了。 //myList.add("abc"); Cat c = new Cat(); Bird b = new Bird(); myList.add(c); myList.add(b); // 获取迭代器 // 这个表示迭代器迭代的是Animal类型。 Iterator<Animal> it = myList.iterator(); while(it.hasNext()){ // 使用泛型之后,每一次迭代返回的数据都是Animal类型。 //Animal a = it.next(); // 这里不需要进行强制类型转换了。直接调用。 //a.move(); // 调用子类型特有的方法还是需要向下转换的! Animal a = it.next(); if(a instanceof Cat) { Cat x = (Cat)a; x.catchMouse(); } if(a instanceof Bird) { Bird y = (Bird)a; y.fly(); } } } } class Animal { // 父类自带方法 public void move(){ System.out.println("动物在移动!"); } } class Cat extends Animal { // 特有方法 public void catchMouse(){ System.out.println("猫抓老鼠!"); } } class Bird extends Animal { // 特有方法 public void fly(){ System.out.println("鸟儿在飞翔!"); } }
-
为什么重写Equals方法要重写HashCode方法
2022-07-30 10:18:55重写目录
在每个类中,重写equals方法的时侯,一定要重写hashcode方法。
Object类中的equals方法,底层是通过==来进行比较,所以比较的是对象的内存地址
1、equals方法
2、hashcode方法
Java中的hashCode方法就是根据一定的规则与对象相关信息(例如对象的存储地址,对象的字段等)映射成一个数组,这个数值就被称为散列值
3、hash算法
就是将hashcode的得到的随机数(散列值),映射成固定长度的值Java中规定:
(1)如果两个对象通过equals方法比较是相等的,那么它们的hashCode方法结果值也是相等的。
(2)如果两个对象通过equals方法比较是不相等的,那么它们的hashCode方法结果值不一定不相等。
很多情况下,我们比较对象并不需要比较对象的地址,而是只要是同一个类的不同对象,成员属性值相同,我们就认为是同一个对象
上图所示,没有重写equals方法的情况下,这里的比较返回的是false(因为比较的是堆中的内存地址)。
4、重写equals方法
但是两个对象是同一个类,而且成员变量的值都是相同,所以我们可以认为是同一个对象,为了达到这个效果,就必须重写equals方法,让他们比较的是类的类型和成员变量的值
这里发现equals比较的是对象的成员变量的值了,并不是比较的内存地址,但是两个对象的hashcode还是不相同,这就会导致如下问题
HashSet有一个特性就是不能允许相同的值的存在,我们car1和car2对于我们来说就是同一个对象(同类型,同值),那么为什么会存在这个问题呢?
我们知道HashSet底层是通过HashMap来实现的,HashMap的key就是我们存入HashSet中的值,而value是一个固定值(并不需要去管),而HashMap的底层是通过数组+链表+红黑树(>=1.8),hashmap底层在计算数组下标位置就是使用的hashcode去实现的hash算法,所以如果hashcode的值不同,计算出来的数字下标位置就有可能不同,所以就将car1和car2放在了不同的数组的位置,所以并不会进行覆盖(正常情况下如果hashcode相同,得到相同的数组下标位置,还需要进行equals来比较是否是同一个元素),所以这就导致Hashset不能起到去重的作用
所以这里也是我们需要重写HashCode方法的原因
5、重写HashCode方法
这里可以看到,重写HashCode方法之后,两个实例对象的hashcode的值也就是相同的,HashSet也就能起到了去重的效果
所以Java中规定,一般重写equals方法就要重写HashCode方法,也是为了保证在不同场景下使用不会出错
-
为什么重写equals方法时必须重写hashcode方法
2021-09-06 19:00:13重写equals()3. hashCode与equals的区别和联系3.1 Hash3.2 HashCode 1. == 与 equals的区别 如果两个引用类型变量使用==运算符,那么比较的是地址,它们分别指向的是否是同一地址的对象,结果一定是false,因为两... -
【Java比较学习】重写equals方法的安全写法
2021-10-05 15:49:11重写equals方法的正确打开方式 正文开始@Assassin 目录:重写equals方法的正确打开方式1. 什么是equals方法?1.1 equals方法:2. 为什么要重写equals方法?2.1 举个例子吧~3. 分析equals源码:4. 正确重写equals方法... -
【面试】hashCode与equals两者之间的关系 / == 和equals / 为什么要重写equals方法 / 重写equals /hashcode...
2020-12-21 08:43:09文章目录1、hashCode与equals两者之间的关系2、== 和equals的区别`3、为什么要重写equals()方法?4、重写equals()方法5、为什么要重写hashCode()方法?6、什么时候需要重写hashCode()方法?7、重写hashCode()方法: ... -
为什么重写equals方法时还要重写hashCode
2021-11-20 11:01:28文章目录前言示例代码结构情景演示情景一:不重写equals与hashCode普通情况下使用在哈希存储结构下使用情景二:仅重写equals普通情况下使用在哈希存储结构下使用情景三:仅重写hashCode普通情况下使用在哈希存储结构... -
Java基础321 - 如何重写equals方法
2022-06-12 16:49:40测试方法 -
重写equals方法时必须重写hashcode方法吗
2022-02-22 13:07:18重写equals方法时必须重写hashcode 有规范: 1,当obj1.equals(obj2) 为 true 时,obj1.hashCode() == obj2.hashCode() 2,当obj1.equals(obj2) 为 false 时,obj1.hashCode() != obj2.hashCode() 原因: 如果只重写... -
java 为什么重写equals方法要重写hashcode方法
2022-06-05 21:30:23Object类是所有类的基类,Object类中有equals方法和hashcode方法。在Object类中:equals方法是通过==进行比较的,比较的是引用指向的对象,如果对象相同,那么就认为两个相等。hashcode方法是获取对象的特征码值,... -
浅谈java 重写equals方法的种种坑
2020-08-25 04:24:37主要介绍了浅谈java 重写equals方法的种种“坑”,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 -
为什么在重写 equals方法的同时必须重写 hashcode方法
2020-09-01 22:44:21Object 类是所有类的父类,其 equals 方法比较的是两个对象的引用指向的地址,hashcode 是一个本地方法,返回的是对象地址值。他们都是通过比较地址来比较对象是否相等的 -
为什么重写equals方法,还必须要重写hashcode方法
2022-04-26 23:15:29我们都知道java中的List集合是有序的,因此是可以重复的,而set集合是无序的,因此是不能重复的,那么怎么能保证不能被放入重复的元素呢,但靠equals方法一样比较的话,如果原来集合中以后又10000个元素了,那么放入... -
重写equals方法就必须重写hashcode的方法的思考
2022-02-24 00:47:06基于以上的java对于Set或者Map的实现要求,所以建议所以需要重写equals方法的类都要同时重写hashcode方法。 二、疑问 这时就会有人问,我就不重写,能发生啥? 那我就来装个逼 下面是我个人理解 1、若是重写equals... -
如何重写equals方法
2021-05-13 10:28:59重写equals方法 我们都知道,如果不对equals方法进行重写的话,那么它默认比较的就是两个对象的地址值是否是一样的。但是我们往往需要比较的是对象的内容是否是一样的,除了几个内置重写了equals方法的类型,我们写... -
重写equals方法一定要重写hashcode方法吗
2021-11-08 21:23:37我们先来看Object的equals方法,也就是我们不重写equals时用的方法 public boolean equals(Object obj) { return (this == obj); } see,就是个==连接的,如果不是基本数据类型就比对象地址值 所以我们如果想... -
Java为什么重写 equals 方法必须重写 hashcode 方法 ?
2022-04-21 21:29:57如果只重写了equals方法,而不重写hashcode的方法,会造成hashcode的值不同,而equals()方法判断出来的结果为true。 在Java中的一些容器中,不允许有两个完全相同的对象,插入的时候,如果判断相同则会进行覆盖。这... -
为什么重写equals方法必须要重写hashCode方法
2022-03-07 18:34:34为什么重写equals时必须要重写hashCode方法 首先让我们看一下关于hashCode的规定: 对象相等,hashCode一定相等 对象不相等,hashCode可能相等 hashCode相等,对象不一定相等 hashCode不相等,对象一定不... -
为什么重写equals方法要重写HashCode方法
2021-08-12 22:38:39为什么重写equals方法要重写HashCode方法 一、为什么重写equals方法要重写HashCode方法 在Object类中HashCode和equals是具有相同表现的 ① 如果两个对象equals为F,则表示两个对象的地址不同,则对应的HashCode不同... -
Java重写equals方法时为什么要重写hashCode方法
2020-07-31 11:37:29在我们平时编写Java代码时,重写equals方法时一定要重写hashCode方法,这是为什么呢? 在讨论这个问题前,我们先看下Object类中hashCode方法和equals方法。 hashCode方法: 翻译如下: equals方法: 翻译如下: ... -
为什么重写equals方法和hashcode方法
2022-03-11 15:31:40其实每个类都有一个equals方法和hashcode方法。因为所有的类都继承自Object类。Object类中定义如下: equals中使用的双等于号进行比较,所以进行比较的是对象的引用。并且这两个方法都未被final修饰,所以都... -
深入浅出!Java 重写Equals方法的种种坑!
2021-08-04 14:15:32重写java object类的equals方法 覆盖equals方法请遵守约定 什么情况下要覆盖equals方法 容易违反的对称性 不易察觉的传递性 覆盖equals请遵守通用约定 似乎覆盖equals方法看起来似乎是一件平常甚至极其简单的事情... -
为什么重写equals方法时一定要重写hashCode方法
2021-07-30 09:25:53在每个类中,在重写 equals 方法的时侯,一定要重写 hashcode 方法。如果不这样做,你的类违反了 hashCode的通用约定, 这会阻止它在 HashMap 和 HashSet 这样的集合中正常工作。 根据 Object 规范,以下时具体约定...