关于Java中的Set集合是不是有必要重写equals和hashCode方法,从代码入手!!!

一、首先,从程序中遇到的问题入手,上代码

/**
 *  @Author: caesar
 *  @Date:2020年12月11日 15:12:47
 *  @Description: 实体类
 */
public class Person {
    private Integer id;
    private String name;

    public Person(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
import java.util.HashSet;
import java.util.Set;

/**
 *  @Author: caesar
 *  @Date:2020年12月10日 17:12:31
 *  @Description: 排序set的测试类
 */
public class SortedSetTest {
    public static void main(String[] args) {

        Set<Person> set = new HashSet<Person>();
        Person person1 = new Person(1,"wsq");
        Person person2 = new Person(1,"wsq");
        set.add(person1);
        set.add(person2);
        System.out.println(set);
    }
}

来运行,看结果。。。

 

 

 呦呵,说好的幸福呢,说好的去重呢???

 

二、问题分析

1、首先补充下基础知识,下面用的到。

  (1)== 比较的是内存地址,也就是对象在内存中的位置

  (2)equals方法中调用的是==,所以比较的也是内存地址

  (3)判断==相同的对象,hashCode一定相同;==不同的对象,hashCode可能相同;hashCode相同的对象,==不一定相同;hashCode不同的对象,==一定不同。

2、然后需要了解Set的去重原理

首先在Set中放如数据的时候,如果Set每次都去调用equals,如果集合中有10000个对象,就需要equals一万次,一万次这个效率。。。。。。所以呢,就采用了hashCode的方法,给每一个对象都根据特定的算法,产生一个hashCode,当在Set中放入数据的时候,先判断hashCode是否相同,如果不同,直接放入。如果hashCode相同,那么再调用equals方法,懂了妥了,一改就ok嘛,简简单单。

 

三、问题解决

重写equals方法就欧克了嘛

/**
 *  @Author: caesar
 *  @Date:2020年12月11日 15:12:00
 *  @Description: 实体类
 */
public class Person {
    private Integer id;
    private String name;

    public Person(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
    /**
     *  @Author: caesar
     *  @Date:2020年12月10日 19:12:31
     *  @Description: 重写equals方法
     */
    @Override
    public boolean equals(Object obj){
        if(this == obj){
            return true;
        }
        if(!(obj instanceof Person)){
            return false;
        }
        Person person = (Person) obj;
        return this.id == ((Person) obj).id && this.name.equals(((Person) obj).name);
    }
}

 

再来,看结果

 

???????why?

不是调用equals方法吗?我改了呀!!!!!!

仔细重新思考一番,恍然大悟

注意,注意,在Set中放入值,先判断的是,hashCode是否相同,相同,再去调用equals方法,不同,直接就放入了,然后呢根据前面的知识,new 的两个person,它们在堆中的位置不同,那么==不同,那么hashCode可能相同,可能不同,人家高大上的算法,hashCode冲突的概率很低的,所以,直接判断就是不同,然后就放入集合了。这就完蛋了。。。

所以,再重写hashCode,让他们的hashCode相同,去调用equals方法,来

package com.example.demo.day2.test1;

/**
 *  @Author: caesar
 *  @Date:2020年12月11日 15:12:00
 *  @Description: 实体类
 */
public class Person {
    private Integer id;
    private String name;

    public Person(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
    /**
     *  @Author: caesar
     *  @Date:2020年12月10日 19:12:31
     *  @Description: 重写equals方法
     */
    @Override
    public boolean equals(Object obj){
        if(this == obj){
            return true;
        }
        if(!(obj instanceof Person)){
            return false;
        }
        Person person = (Person) obj;
        return this.id == ((Person) obj).id && this.name.equals(((Person) obj).name);
    }
    /**
     *  @Author: caesar
     *  @Date:2020年12月10日 19:12:47
     *  @Description: 重写hashCode方法
     */
    @Override
    public int hashCode(){
        int result = 1;
        result = result * 31 + id;
        result = result * 31 + name.hashCode();
        return result;
    }
}

再测:

 

 搞定,这也就是平是有人说,只重写equals方法可以吗,当人不可以啦,这个之所以重复,首先就是判断hashCode不同了,所以先要重写hashCode方法,在重写equals方法,搞定!!!

 

posted @ 2020-12-11 15:28  码在江湖  阅读(666)  评论(0)    收藏  举报