先上结论:如果需要将自定义类对象作为HashMap的key,那么自定义类中需要重写hashCode()和equals()
Object.class
public boolean equals(Object obj) {
return (this == obj);
}
public native int hashCode();//非Java语言的实现,直接来源于JVM底层
HashMap.class
在进行Put操作的时候会匹配key.hashCode的hash是否一样,如果不一样的就直
接进行插入操作了,如果hash一样的情况下,就会进行equal的比较,去比较两个
对象是否一样,看Map中是否存在该对象了.
实例:
当你新建两个Integer对象
Integer i1 = new Integer(1);
Integer i2 = new Integer(1);
这两个对象是不等的:i1==i2结果显然为false,但是这两个对象的引用是一样
的,也就是引用的1来源于同一个地址。为什么要说这个?看下面代码:
HashMap iMap = new HashMap<>();
iMap.put(i1,1);
iMap.put(i2,2);
System.out.println(iMap.get(i1));
System.out.println(iMap.get(i2));
清楚结果了?输出的结果为两个2,常识上的理解,这个结果是正常,非常赞同。
看到下面的自定义class对象:
public static void main(String[] args) {
Student stu1 = new ArrayListDemo().new Student("Mrlj", "B");
Student stu2 = new ArrayListDemo().new Student("Mrlj", "B");
HashMap hMap = new HashMap<>();
System.out.println("--------------put操作----------------");
hMap.put(stu1, "1");
hMap.put(stu2, "2");
System.out.println("--------------Get操作----------------");
System.out.println(hMap.get(stu1));
System.out.println(hMap.get(stu2));
}
public class Student {
private String name;
private String sex;
public Student(String name, String sex) {
this.name = name;
this.sex = sex;
}
}
上面新建的两个对象中,两个对象的地址不同,但里面的引用相同,和前面讨论的
Integer一样,但是实际输出的结果为1和2,懵了吧!
HashMap中的hashCode是重写Object类的,传入的参数也是Object,也就是默认
对比的是Object的本身,上面的两个Integer显然是两个不同的对象,直接对比肯
定为false,原因是封装类Integer中重写了Object.class中的hashCode()和equals()
方法,也就是在Integer.class内修改了hashCode()和equals()的规则,你们想
要使用Integer,需要调用Object.class中的方法,Object.class作为所有类的
基类,我Integer默认隐式的继承了Object并重写了其中的方法,你要用Object中
的方法也得看son中有没有啊,别老是麻烦father,说到这里上面的所有问题几乎
都迎刃而解了,那就是在自定义的类中重写hashCode()和equals()阿,定自己的
规则。在HashMap中,equals()是在hashCode()匹配相等之后再使用的,如果
hashCode()匹配不等,程序压根就不调用equals(),这是HashMap源码中定的规则,
到此已经全部讲解完了,告辞!
实例代码:
public static void main(String[] args) {
Student stu1 = new HashMapDemo().new Student("Mrlj", "B");
Student stu2 = new HashMapDemo().new Student("Mrlj", "B");
HashMap hMap = new HashMap<>();
System.out.println("--------------put操作----------------");
hMap.put(stu1, "1");
hMap.put(stu2, "2");
System.out.println("--------------Get操作----------------");
System.out.println(hMap.get(stu1));
System.out.println(hMap.get(stu2));
}
public class Student {
private String name;
private String sex;
public Student(String name, String sex) {
this.name = name;
this.sex = sex;
}
@Override
public boolean equals(Object o) {
if (o instanceof Student) {
Student stu = (Student)o;
System.out.println("this:"+(name+sex)+" "+"that:"+stu.getName()+stu.getSex());
return (name+sex).equalsIgnoreCase(stu.getName().trim()+stu.getSex().trim());
}
return false;
}
@Override
public int hashCode() {
System.out.println("hashCode:"+(name+sex).hashCode());
return (name+sex).hashCode();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
如果为:
Student stu1 = new HashMapDemo().new Student("Mrlj", "B");
Student stu2 = new HashMapDemo().new Student("Mrlj", "B");
输出:
--------------put操作----------------
hashCode:74614431
hashCode:74614431
this:MrljB that:MrljB
--------------Get操作----------------
hashCode:74614431
2
hashCode:74614431
this:MrljB that:MrljB
2
如果为:
Student stu1 = new HashMapDemo().new Student("Mrlj", "B");
Student stu2 = new HashMapDemo().new Student("Miss", "B");
输出:
--------------put操作----------------
hashCode:74614431
hashCode:74353318
--------------Get操作----------------
hashCode:74614431
1
hashCode:74353318
2
看到了没,stu1.equals(stu2)为false的时候HashCode压根就不会调用.equals().