先上来一段代码
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那些事儿
我只是大自然的搬运工。