什么时候使用HashMap要重写hashCode()和equals()?

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/QQB67G8COM/article/details/89321027

先上结论:如果需要将自定义类对象作为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<Integer,Integer> 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<Student, String> 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<Student, String> 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().

猜你喜欢

转载自blog.csdn.net/QQB67G8COM/article/details/89321027