作为HashMap的key的自定义类需要重写hashCode()和equals()

  • Post author:
  • Post category:其他



本文参考自两篇文章,各取其长,整理这篇文章。


文章来源:

https://blog.csdn.net/tuolaji8/article/details/48417031

equals()方法在Object类中的定义:

public boolean equals(Object obj){
    return (this == obj);
}

equals()的定义为:

public native int hashCode();

是一个本地方法,返回的对象的地址值。


1.hashcode()和equals()是在哪里被用到的?什么用的?

HashMap是基于散列函数,在jdk1.7中以数组和链表的方式实现、在jdk1.8中以数组+链表+红黑树的形式实现。而对于每一个对象,通过其hashCode()方法可为其生成一个整形值(散列码),该整型值被处理后,将会作为数组(Map.Entry[])下标,存放该对象所对应的Entry(存放该对象及其对应值)。

equals()方法则是在HashMap中插入值或查询时会使用到。当HashMap中插入 值或查询值对应的散列码与数组中的散列码相等时,则会通过equals方法比较key值是否相等,所以想以自建对象作为HashMap的key,必须重写 该对象继承object的equals方法。



2.本来不就有hashcode()和equals()了么?干嘛要重写,直接用原来的不行么?

HashMap中,如果要比较key是否相等,要同时使用这两个函数!因为自定义的类的hashcode()方法继承于Object类,其hashcode码为默认的内存地 址,这样即便有相同含义的两个对象,比较也是不相等的,例如,

Student st1 = new Student("wei","man");
Student st2 = new Student("wei","man"); 

正常理解这两个对象再存入到hashMap中应该是相等的,但如果你不重写 hashcode()方法的话,比较是其地址,不相等!

如果对上面的例子不能理解的话,就参考如下代码,照理来说str2中的内容会覆盖掉str1的内容,而上面的例子没有重写hashCode()和equals()方法是不行的,String中有重写equals()和hashCode()方法了。:

Map<String,String> map = new HashMap<>() ;
String str1 = "demo" ;
String str2 = "demo" ;
map.put(str1,"hello") ;
map.put(str2,"hello") ;

HashMap中的比较key是这样的,先求出key的hashcode(),比较其值是否相等,若相等再比较equals(),若相等则认为他们是相等 的。若equals()不相等则认为他们不相等。如果只重写hashcode()不重写equals()方法,当比较equals()时只是看他们是否为 同一对象(即进行内存地址的比较),所以必定要两个方法一起重写。HashMap用来判断key是否相等的方法,其实是调用了HashSet判断加入元素 是否相等。

接下来是另一篇博客的一个例子,供大家学习参考


文章来源:

https://blog.csdn.net/qq_35489960/article/details/78926547

自定义  PhoneNumber类

package comjk;

public class PhoneNumber {
   private int prefix; //区号
   private int phoneNumber; //电话号
public int getPrefix() {
    return prefix;
}
public void setPrefix(int prefix) {
    this.prefix = prefix;
}
public int getPhoneNumber() {
    return phoneNumber;
}
public void setPhoneNumber(int phoneNumber) {
    this.phoneNumber = phoneNumber;
}
   
   
}

//main 方法
 public static void main(String[] args) {
 
     Map<PhoneNumber, String> map =new  HashMap<PhoneNumber, String>();
     PhoneNumber phoneNumber1=new PhoneNumber();
     phoneNumber1.setPhoneNumber(111);
     phoneNumber1.setPrefix(111);
     PhoneNumber phoneNumber2=new PhoneNumber();
     phoneNumber2.setPhoneNumber(222);
     phoneNumber2.setPrefix(222);
     map.put(phoneNumber1, "111");
     map.put(phoneNumber2, "222");
 
     System.out.println(map.get(phoneNumber1));
     System.out.println(map.get(phoneNumber2));
 
     PhoneNumber phoneNumber3=new PhoneNumber();
     //参数内容和phoneNumber2一样
     phoneNumber3.setPhoneNumber(222);
     phoneNumber3.setPrefix(222);
     System.out.println(map.get(phoneNumber3));
   
 }


 输出结果

 111
 222
 null    //因为没有重写hashCode和equals方法,所以取不出phoneNumber2的值,因为这里phonenumber2和phonenumber3地址不同。


  //在PhoneNumber 类中重写equals()和hashCode()方法;
  @Override
   public boolean equals(Object o)
   {
       if(this == o)
       {
           return true;
       }
       if(!(o instanceof PhoneNumber))
       {
           return false;
       }
       PhoneNumber pn = (PhoneNumber)o;
       return pn.prefix == prefix && pn.phoneNumber == phoneNumber;
   }


   @Override
   public int hashCode()
   {
       int result = 17;
       result = 31 * result + prefix;
       result = 31 * result + phoneNumber;
       return result;
   }


 输出结果

  111
  222
  222