十万个为什么之为什么要重写hashcode()方法

为什么要重写hashcode方法

    • 前言
    • 一、equals()方法原理
    • 二、equals()方法验证
      • 1.未重写equals方法
      • 2.重写equals()方法
      • 3.总结:
    • 三、为什么重写equals()的同时还得重写hashCode()
      • 1.因为对象没有重写hashCode()方法,使用是Object默认的hashCode()方法,导致对象内容一致但是地址不一样。
      • 2.Java API文档中关于hashCode方法有以下几点规定:
      • 1.未重写hashCode()方法
      • 2.重写hashCode()方法
      • 2.总结

前言

十万个为什么之为什么要重写hashcode()方法???

equals比较的是对象的内容,==比较的是对象的地址。

equals()和hashcode()都是属于超类(Object)类中的基本方法,咱们先来看看equals()方法。

一、equals()方法原理

equals()方法默认是超类(Object)对象的一个基本方法,用于检测两个对象是否相等 (其实就是判断两个对象是否具有相同的引用)。

源码:

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

首先所有的对象都拥有标识(内存地址)和状态(数据/内容),同时==比较的是对象的地址,所以Object的equals()比较的是对象的地址。

二、equals()方法验证

定义一个实体类:

class User{
        private String userName;
 
        public User(String userName) {
            this.userName = userName;
        }
 
        public String getUserName() {
            return userName;
        }
 
        public void setUserName(String userName) {
            this.userName = userName;
        }
 
    }

1.未重写equals方法

 @Test
 public void test01(){
      User user1 = new User("詹三");
      User user2 = new User("詹三");
      // 结果
      // false
      System.out.println(user1.equals(user2));
      // false
      System.out.println(user1 == user2);
  }

打印结果都是false,为什么?

结果就是上面所说:

①==比较的是对象的地址不是对象的内存。

②Object的equals()方法默认实现是==。

2.重写equals()方法

 @Override
 public boolean equals(Object obj) {
       // return super.equals(obj);
       // if (obj.getClass().equals(User.class)) {}
       if (obj instanceof User) {
          User c = (User) obj;
          return userName == c.userName;
       }
     return false;
 }

使用instanceof判断对象是否是User对象,再判断对象内容userName,相同为true否则为false

3.总结:

默认情况下从超类Object继承而来的equals方法与‘==’是完全等价的,比较的都是对象的内存地址,

但我们可以重写equals方法,使其按照我们的需求的方式进行比较。

三、为什么重写equals()的同时还得重写hashCode()

主要是运用到Key-Value集合中时,比如HashMap/HashTable/HaspSet, 将对象作为Key保存到集合中,在以“相等的”(equals()返回true)的另一个对象作为Key去查询对应的数据时, 根本找不到,为什么?

1.因为对象没有重写hashCode()方法,使用是Object默认的hashCode()方法,导致对象内容一致但是地址不一样。

2.Java API文档中关于hashCode方法有以下几点规定:

①在java应用程序执行期间,如果在equals方法比较中所用的信息没有被修改,那么在同一个对象上多次调用hashCode方法时必须一致地返回相同的整数。如果多次执行同一个应用时,不要求该整数必须相同。

②如果两个对象通过调用equals方法是相等的,那么这两个对象调用hashCode方法必须返回相同的整数。

③如果两个对象通过调用equals方法是不相等的,不要求这两个对象调用hashCode方法必须返回不同的整数。但是程序员应该意识到对不同的对象产生不同的hash值可以提供哈希表的性能。

1.未重写hashCode()方法

@Test
    public void test02(){
        User user1 = new User("詹三");
        User user2 = new User("詹三");
        // 结果
        // true
        System.out.println(user1.equals(user2));
        System.out.println("user1.hashCode())>>>"+ user1.hashCode());
        System.out.println("user2.hashCode())>>>"+ user2.hashCode());
        // 以“相等的”(equals()返回true)的另一个对象作为Key去查询对应的数据
        HashMap hashMap = new HashMap();
        hashMap.put(user1, "詹三");
        System.out.println("user1>>Key" + hashMap.get(user1));
        System.out.println("user2>>Key" + hashMap.get(user2));
    }

两个对象的hashcode值完全不一致,再以“相等的”(equals()返回true)的另一个对象作为Key去查询对应的数据为null,完全违反Java API文档中关于hashCode方法第二点规定。

2.重写hashCode()方法

这里直接使用Objects.hash(userName);

    @Override
        public int hashCode() {
            // return super.hashCode();
            return Objects.hash(userName);
        }

两个对象的hashcode值一致,再以“相等的”(equals()返回true)的另一个对象作为Key去查询对应的数据一致。

2.总结

1.Map/sET等集合类型存放的对象必须是唯一的。

2.集合类判断对象是否相等,先equals()方法在hashCode()方法,必须都返回true。

3.由于Object默认的hashCode()方法返回的是对象的hash值,不是对象内容(参数值)的hash值,所以需要重写。

你可能感兴趣的:(#,每日一问,java,开发语言)