自定义类的equals有用吗 ?

本文探讨了Java中如何正确地实现对象相等性的检查,特别是对于自定义类在Set和HashMap中的表现。通过重写equals和hashCode方法,确保了对象在集合中的正确行为。

先上来一段代码

import java.util.HashSet;
import java.util.Set;

/**
 * 利用set集合查看对象是否相等,因为set里面的元素是不可以重复的
 * @author hjm
 *
 */
public class EqualsSetDemo01 {

public static void main(String[] args) {

    String str2 = new String("abc");
    String str3 = new String("abc");

    Set<String> set = new HashSet<String>();
    set.add(str3);
    set.add(str2);
    System.out.println("set的元素有"+set.size()+"个");//1

    Set<Person> pset2 = new HashSet<Person>();

    Person person1 = new Person("he");
    Person person2 = new Person("he");
    pset2.add(person1);
    pset2.add(person2);
    System.out.println("set2的元素有"+pset2.size()+"个");//2

}

}
class Person{

private String name;

public Person(String name) {
    super();
    this.name = name;
}
/*
 * 用来判断两个person是否相同
 */
public boolean isSame(Person person) {
    if(this.name.equals(person.name))
    {
        return true;
    }
    return false;

}

}

这里面有一个问题,那就是String类的对象和Person的对象明明都是两个不同的对象,为什么就只有person的set里头是两个,String的set里头元素是一个?

我们之前试图通过自己定义一个boolean方法来判断Person对象是否相等,用到了属性名相等,发现这个方法不起作用,还是一样的是两个元素放进去了,这样子的话,在生活中会出现什么状况呢?比如你发工资给某位员工,按照这个结果你会重复多发一次,即使用到了set集合去重也不行 是不是很坑? 那我们要怎样真正去区别两个不一样元素呢?

看到了String的set集合中只有一个元素,为啥呢?因为String重写了父类即Object的equals方法, 不仅对引用地址进行了比较,还对其内容值进行了昨个比较 ,二者有一即可。

再看我们 的person类,也默认继承了Object类,但是没有重写了父类的equals方法,父类的equals方法只对引用地址进行比较,因为两个person对象开辟了两个空间,自然不是同一个 对象,因此set集合也就自然把他们都放进去了。

所以在Person类中我们要重写equals方法,记住是重写,重写跟重载是不一样的概念。

重载:就是在同一个类中,方法的名字相同,但参数个数、参数的类型不同。

重写:它是指子类和父类的关系,子类重写了父类的方法,但方法名、参数类型、参数个数必须相同

重写更加严格规范。

@Override
public boolean equals(Object obj) {
    if(this==obj) {
        return true;
    }

    if(obj instanceof Person){
        return this.name.equals(((Person) obj).name);

    }
    return false;

}

这么写我们再看下是否可以判断是同一个人了,我们先用list集合的equals方法进行判断是否是同一个人?

    //引入list看下是person的两个实例是否一致
    List<Person> pList = new  ArrayList<Person>();
    pList.add(person2);
    pList.add(person1);
    System.out.println("List集合中有"+pList.size());//2
    System.out.println(person1.equals(person2));//true 

在list中用equals可以判断是同一个人,那么在set集合中再试一下是否是同一个人呢?

    Person person1 = new Person("he");
    Person person2 = new Person("he");
    pset2.add(person1);
    pset2.add(person2);
    System.out.println("set2的元素 有"+pset2.size()+"个");//2
   //set2的元素有2个

发现还是两个人,到现在还是无法让person的两个人变成一个人?

很明显,Person这个类在重写equals()方法后,虽然已经支持List,但还不支持Set。要完美支持HashMap,HashSet,LinkedHashMap,ConcurrentHashMap等这些类,不但要重写equals方法,还需要重写hashCode()方法。

所以我们重写了hashcode方法 !

@Override
public int hashCode() {
    return name.hashCode();
}

这下我们再看一下到底是几个人?

Person person1 = new Person("he");
Person person2 = new Person("he");
pset2.add(person1);
pset2.add(person2);
System.out.println("set2的元素 有"+pset2.size()+"个");//2
//set2的元素有1个

历经千辛万苦 现在已经终于变成一个人了。

总结:当我们在实际业务中需要重写(覆盖)equals方法时,根据规范,我们一定要重写(覆盖)hashCode方法。在实际开发过程中,不建议一上来就重写equals方法,除非你有特殊的需求。

本篇思路来自于https://zhuanlan.zhihu.com/p/27741179
-java那些事儿

我只是大自然的搬运工。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值