HashMap重写equals和hashcode的问题
目录
为什么在Hashmap中重写equals一定要对hashcode重写?
什么时候对equals,hashcode重写?
1 当需要比较对象是否相同时需要重写equals
2 当需要使用HashMap并且需要重写equals方法时,都需要重写hashcode方法!不需要使用hashmap的话是不需要重写的
什么是hashcode方法?
hashcode方法是Java的java.lang.Object提供的本地方法,这个方法在jvm中实现,它能返回当前对象在内存中地址。
public native int hashCode();
为什么在Hashmap中重写equals一定要对hashcode重写?
1(正向论证) HashMap在put一个键值对时,会先根据键的hashCode和equals方法来同时判断该键在容器(红黑树或表)中是否已经存在,如果存在则覆盖,反之新建。所以如果我们在重写equals方法时,没有重写hashCode方法,那么hashCode方法还是会默认使用Object提供的原始方法,而Object提供的hashCode方法返回值是不会重复的(也就是说每个对象返回的值都不一样)。所以就会导致每个对象在HashMap中都会是一个新的键。
2(反向论证) 若一个类中重写了 equals 方法,没有重写hashCode方法;且该类的两个对象具有不同属性但 hashCode 相等(有可能是相等的),在hashMap 以该对象为键进行存储时,会出现hash冲突现象,但发现该类重写了equals 方法,且通过该类的equals 比较之后也是相等,就会出现 hashMap 中只保存了一个对象,采用get 方法获取时,就会获取到别的对象,从而导致获取对象错乱。
怎样重写hashcode与equals方法?
我们直接上实例,然后再说明
-
import org.w3c.dom.Entity;
-
-
import java.util.HashMap;
-
import java.util.Map;
-
import java.util.Objects;
-
-
public class Main {
-
public static void main(String[] args) {
-
Map_1();
-
}
-
public static void Map_1()
-
{
-
Student s1=new Student("张三",21,"男","net2班");
-
Student s2=new Student("李四",22,"女","java1班");
-
boolean s=s1.equals(s2);
-
System.out.println(s1.toString());
-
System.out.println(s2.toString());
-
-
HashMap<Student,Integer> ha1=new HashMap<Student, Integer>();
-
ha1.put(s1,32);
-
ha1.put(s2,122);
-
for(Map.Entry<Student,Integer> entry:ha1.entrySet()){
-
System.out.println(entry.getKey());
-
System.out.println(entry.getValue());
-
}
-
}
-
}
-
-
class Student {
-
private String name;
-
private Integer age;
-
private String sex;
-
private String className;
-
-
Student(String name, Integer age, String sex, String className) {
-
this.name = name;
-
this.age = age;
-
this.sex = sex;
-
this.className = className;
-
}
-
-
public String getName() {
-
return name;
-
}
-
-
public void setName(String name) {
-
this.name = name;
-
}
-
-
public Integer getAge() {
-
return age;
-
}
-
-
public void setAge(int age) {
-
this.age = age;
-
}
-
-
public String getSex() {
-
return sex;
-
}
-
-
/**
-
* @param sex 男 女
-
*/
-
public boolean setSex(String sex) {
-
if (!Objects.equals(sex, "男") && !Objects.equals(sex, "女")) {
-
return false;
-
} else {
-
this.sex = sex;
-
return true;
-
}
-
-
}
-
-
public String getClassName() {
-
return className;
-
}
-
-
public void setClassName(String className) {
-
this.className = className;
-
}
-
-
-
public String toString() {
-
return name " " sex " " age " " className;
-
}
-
-
-
public boolean equals(Object o) {
-
if (o instanceof Student) {
-
return Objects.equals(((Student) o).getName(), this.name) && Objects.equals(((Student) o).getAge(), this.age) && Objects.equals(((Student) o).getClassName(), this.className) && Objects.equals(((Student) o).getSex(), this.sex);
-
} else
-
return false;
-
}
-
-
-
public int hashCode() {
-
final int prime = 31;
-
int result = 1;
-
result = prime * result ((sex == null) ? 0 : sex.hashCode());
-
result = prime * result ((name == null) ? 0 : name.hashCode());
-
result = prime * result ((className == null) ? 0 : className.hashCode());
-
result = prime * result (age == null ? 0 : age.hashCode());
-
-
return result;
-
}
-
}
hashCode书写方法
1 我们比较对象中的每一个属性 如果属性==null,我们返回hashcode为0,
反之将调用hashCode方法获得当前属性的地址 (31*result) 并将结果赋值给result
2 直到每一个属性都已比较完成,我们返回累加的result值
为什么使用31?为什么使用hashCode方法
1 其实每次计算result*31的作用是为了,防止hash冲突!因为如果不设置一个乘积因子,result计算的结果比较小,非常容易在累加的过程后出现相同的hash值,这种情况不是我们想见到的!
2 首先我们需要知道,我们是通过对象的域来计算hash的, 在对象中域无非数组、引用类型、基本数据类型,有这么多类型的域,我们肯定不能选择某一个域的hash值来作为对象的hashcode方法的返回值;因此我们考虑将域的hash值累加起来返回!
- 基本数据类型,大家可以参考其对应的包装类型的hashcode方法
- (我们可以发现实例代码中age属性使用的是Integer而不是int类型)
- 引用类型则直接调用hashcode()
- 数组类型则需要遍历数组,依次调用hashcode()
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgakeca
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13