先上来一段代码
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那些事儿
我只是大自然的搬运工。
本文探讨了Java中如何正确地实现对象相等性的检查,特别是对于自定义类在Set和HashMap中的表现。通过重写equals和hashCode方法,确保了对象在集合中的正确行为。
142

被折叠的 条评论
为什么被折叠?



