集合List和Map——重写equals和hashCode方法(集合元素是类的对象)-爱代码爱编程
解决了当List集合里面的元素是类的对象,而不是String,Integer等类型时,怎么使用contains方法和indexOf方法
解决了map的key值是类的对象时,怎么用具有相同内容的不同对象,获取相同的value值
List重写equals方法来使用contains与indexOf方法
equals方法用于contains与indexOf方法中,equals可以正常的比较String,Integer等类型的对象,但是对于自己创建的类对象,无法正确判断,因此在自己定义的类里面需要重写equals,才能正常使用contains与indexOf方法
同样的,如果不用这两个方法,就不需要重写equals
package test.ListDemo;
import java.util.*;
public class equalsDemo1 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("hadoop");
list.add("zookeeper");
System.out.println(list.contains("hadoop"));
System.out.println(list.indexOf("zookeeper"));
//创建一个新的但是相同内容的对象
System.out.println(list.contains(new String("hadoop")));
System.out.println(list.indexOf(new String("zookeeper")));
}
}
结果为
这里是因为String类中已经定义好了equals方法,不需要我们重写,但如果List中的元素不是String类型,而是我们自己定义的类的对象,就需要重写equals方法,看一下这个例子
package test.ListDemo;
import java.util.*;
public class equalsDemo2 {
public static void main(String[] args) {
List<Rectangle> list = new ArrayList<>();
Rectangle r1 = new Rectangle(3,4);
Rectangle r2 = new Rectangle(3,4);
list.add(r1);
System.out.println(list.contains(r1));
System.out.println(list.contains(r2));
System.out.println(list.indexOf(r1));
System.out.println(list.indexOf(r2));
}
}
class Rectangle{
public int length;
public int width;
public Rectangle(){}
public Rectangle(int l,int w){
length = l;
width = w;
}
}
结果为
发现,虽然 r1 和 r2 的参数一样,可以看成是一个对象,但是 r2 使用contains方法和indexOf方法返回的结果却和 r1不一样,为了解决这个问题,就需要重写equals方法
package test.ListDemo;
import java.util.*;
public class equalsDemo2 {
public static void main(String[] args) {
List<Rectangle> list = new ArrayList<>();
Rectangle r1 = new Rectangle(3,4);
Rectangle r2 = new Rectangle(3,4);
list.add(r1);
System.out.println(list.contains(r1));
System.out.println(list.contains(r2));
System.out.println(list.indexOf(r1));
System.out.println(list.indexOf(r2));
}
}
class Rectangle{
public int length;
public int width;
public Rectangle(){}
public Rectangle(int l,int w){
length = l;
width = w;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof Rectangle){
Rectangle r = (Rectangle) obj;
return this.length==r.length && this.width==r.width;
}
return false;
}
}
结果为
发现两者的结果现在都是正确而且相同的了
另外补充一下,由于我这里的类的成员变量都是int类型,所以equals方法中用 == 就可以了,如果有String类型,就可以用
Objects.equals(this.参数,r.参数)
的方式
Map,相同内容的不同对象,应该返回相同的value值
具有相同内容的不同对象,查询返回的value应该是相同的。如果我们没有重写equals方法和hashCode方法,那么就算内容相同,map.get()方法返回的value值也是不一样的
先来看例子
package test.MapDemo;
import java.util.*;
public class equalsDemo2 {
public static void main(String[] args) {
Person p1 = new Person("zhang",12);
Map<Person,Integer> map = new HashMap<>();
map.put(p1,123);
Person p2 = new Person("zhang",12);
System.out.println(p1==p2);
System.out.println(p1.equals(p2));
System.out.println(map.get(p1));
System.out.println(map.get(p2));
}
}
class Person{
public String name;
public int age;
public Person(){}
public Person(String n,int a){
name = n;
age = a;
}
结果为
可以发现,虽然内容p1和p2里面的参数值都是相同的,但是p2是找不到对应的value值的,因此需要重写equals方法和hashCode方法
例子如下
package test.MapDemo;
import java.util.*;
public class equalsDemo2 {
public static void main(String[] args) {
Person p1 = new Person("zhang",12);
Map<Person,Integer> map = new HashMap<>();
map.put(p1,123);
Person p2 = new Person("zhang",12);
System.out.println(p1==p2);
System.out.println(p1.equals(p2));
System.out.println(map.get(p1));
System.out.println(map.get(p2));
}
}
class Person{
public String name;
public int age;
public Person(){}
public Person(String n,int a){
name = n;
age = a;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof Person){
Person p = (Person) obj;
return Objects.equals(this.name,p.name) && this.age == p.age;
}
return false;
}
public int hashCode(){
return Objects.hash(name,age);
}
}
结果为
这次的结果正确了