作者:苏绿儿520 | 来源:互联网 | 2023-01-08 14:11
今天用到了HashMap,HashMap<GPSPoint,Integer>但是当新建另外一个GPSPoint的时候却取不到对应的valueMap<GPSPoin
今天用到了HashMap,HashMap
但是当新建另外一个GPSPoint的时候却取不到对应的value
Map map=new HashMap();
for(int i=0;i<5;i++){
GPSPoint p=new GPSPoint(i,i,i,i);
map.put(p, i);
}
GPSPoint p=new GPSPoint(2,2,2,2);
int i=map.get(p);
System.out.println(i);
深入了解了才知道每个对象实例对应一个hashCode,对应着内存地址
而hashMap通过key查找是找hashCode
更加深入了解,请见另外一篇 深入解析Java对象的hashCode和hashCode在HashMap的底层数据结构的应用
重写hashCode()时最重要的原因就是:
无论何时,对同一个对象调用hashCode()都应该生成同样的值。如果在将一个对象用put()方法添加进HashMap时产生一个hashCode()值,而用get()取出时却产生了另外一个 hashCode()值,那么就无法重新取得该对象了。所以,如果你的hashCode()方法依赖于对象中易变的数据,那用户就要小心了,因为此数据发生变化时,hashCode()就会产生一个不同的hash码,相当于产生了一个不同的“键”。 Object的hashCode()方法,返回的是当前对象的内存地址。下次如果我们需要取一个一样的“键”对应的键值对的时候,我们就无法得到一样的hashCode值了。因为我们后来创建的“键”对象已经不是存入HashMap中的那个内存地址的对象了。
下面看看怎么重写hashCode
1、我们应该先了解java判断两个对象是否相等的规则。
在java的集合中,判断两个对象是否相等的规则是:
1 首先,判断两个对象的hashCode是否相等
2 如果不相等,认为两个对象也不相等
3 如果相等,则判断两个对象用equals运算是否相等
4 如果不相等,认为两个对象也不相等
5 如果相等,认为两个对象相等
我们在equals方法中需要向下转型,效率很低,所以先判断hashCode方法可以提高效率
- package test;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public class Student {
- private String name;
- private Integer age;
- private String identityId;
-
-
- public Student(){};
-
- public Student(String name, String identityId) {
- super();
- this.name = name;
- this.identityId = identityId;
- }
- public String getIdentityId() {
- return identityId;
- }
- public void setIdentityId(String identityId) {
- this.identityId = identityId;
- }
-
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Integer getAge() {
- return age;
- }
- public void setAge(Integer age) {
- this.age = age;
- }
- @Override
- public String toString() {
- return "Student [age=" + age + ", name=" + name + "]";
- }
-
- @Override
- public boolean equals(Object o){
-
-
- if(this == o){
- return true;
- }
-
-
- if(!(o instanceof Student)){
- return false;
- }
-
-
- Student s = (Student)o;
-
-
- return this.name.equals(s.getName()) && this.identityId.equals(s.getIdentityId());
- }
-
- @Override
- public int hashCode(){
- int result = 19;
- result = 31 * result + name.hashCode();
- result = 31 * result + identityId.hashCode();
- return result;
- }
-
- public static void main(String[] args) {
- Student s1 = new Student("name1","1234");
- Student s2 = new Student("name1","1234");
- System.out.println(s1.equals(s2));
- }
-
- }
(1)为对象内每个有意义的属性f(即每个用作equals()比较标准的属性)计算出一个int类型的hashCode值。计算方法如下表所示:
属性类型
计算方式
boolean
hashCode = (f ? 0 : 1);
整数类型(byte、short、char、int)
hashCode = (int)f;
long
hashCode = (int)(f ^ (f >>>32));
float
hashCode = Float.floatToIntBits(f);
double
long l = Double.doubleToLongBits(f);
hashCode = (int)(l ^ (l >>> 32));
普通引用类型
hashCode = f.hashCode();
(2)使用第1步计算出来多个hashCode组合计算出一个hashCode值返回。例如如下代码:
return f1.hashCode() + (int)f2;
如果为了避免直接相加产生偶然相等(两个对象的f1、f2属性并不相等,但他们的和恰好相等),可以通过为各属性乘以任意一个质数后再相加。例如如下代码:
return f1.hashCode() * 17+ (int)f2 * 13;