为什么Hash类容器,放入的元素必须复写hashCode()方法和equals()方法?

1 篇文章 0 订阅
1 篇文章 0 订阅

**

为什么Hash类容器,放入的元素必须复写hashCode()方法和equals()方法?

**

	首先,题目本身就有错误:为什么Hash类容器,放入的元素“必须”覆写hashCode()方法和equals()方法?
	“必须”两字错了,也就是说,不一定要覆写hashCode()和equals()方法。但是,在那种情况下可以不用覆写呢?

下面我举两个例子:

A:自定义对象,作为value放入HashMap时,无需考虑hashCode()和equals()方法的覆写。

示例:

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

//建立一个Student类
class Student1{
	private int id;//学号
	private String name;//姓名
	//有参构造器
	public Student1(int id,String name) {
		this.id = id;
		this.name = name;
	}
	//重写toString方法
	public String toString() {
		return "学号:"+id+","+"姓名:"+name;
	}
}

public class Object_Values {
	public static void main(String[] args) {
		//实例化Map对象,Integer-key,Student-values
		Map<Integer,Student> map = new HashMap<>();
		
		//在Map集合中加入元素
		map.put(1,new Student(1001,"张三"));
		map.put(2,new Student(1001,"张三"));
		map.put(3,new Student(1003,"李四"));
		map.put(4,new Student(1004,"王五"));
		
		//声明Collection集合
		Collection<Student> co = map.values();
		//实例化迭代器
		Iterator<Student> itr = co.iterator();
		//通过迭代器遍历Collection集合
		while(itr.hasNext()) {
			//取出集合元素
			Student std = itr.next();
			System.out.println(std);
		}	
	}
}

输出结果:
输出结果1
可以看到第一行和第二行的结果是一样的,但是没有输出异常,说明Student对象成功放入到了HashMap中。

如果覆写了hashCode()和equals()方法:
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

//建立一个Student类
class Student1{
	private int id;//学号
	private String name;//姓名
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student1 other = (Student1) obj;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	//有参构造器
	public Student1(int id,String name) {
		this.id = id;
		this.name = name;
	}
	//重写toString方法
	public String toString() {
		return "学号:"+id+","+"姓名:"+name;
	}
}

public class Object_Values {
	public static void main(String[] args) {
		//实例化Map对象,Integer-key,Student-values
		Map<Integer,Student> map = new HashMap<>();
		
		//在Map集合中加入元素
		map.put(1,new Student(1001,"张三"));
		map.put(2,new Student(1001,"张三"));
		map.put(3,new Student(1003,"李四"));
		map.put(4,new Student(1004,"王五"));
		
		//声明Collection集合
		Collection<Student> co = map.values();
		//实例化迭代器
		Iterator<Student> itr = co.iterator();
		//通过迭代器遍历Collection集合
		while(itr.hasNext()) {
			//取出集合元素
			Student std = itr.next();
			System.out.println(std);
		}	
	}
}

输出结果:
在这里插入图片描述
结果还是一样的。
说明:自定义对象,作为value放入HashMap时,无需考虑hashCode()和equals()方法的覆写。

A:自定义对象,作为key放入HashMap时,一定要覆写hashCode()和equals()方法。

示例:

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

//建立一个Student类
class Student{
	private int id;//学号
	private String name;//姓名
	
	//有参构造器
	public Student(int id,String name) {
		this.id = id;
		this.name = name;
	}
	//重写toString方法
	public String toString() {
		return "学号:"+id+","+"姓名:"+name;
	}
}

public class Object_Key {
	public static void main(String[] args) {
		//实例化Map对象,Student-key,Integer-values
		Map<Student,Integer> map = new HashMap<>();
		
		//在Map集合中加入元素
		map.put(new Student(1001,"张三"),1);
		map.put(new Student(1001,"张三"),2);
		map.put(new Student(1003,"李四"),3);
		map.put(new Student(1004,"王五"),4);
		
		//获得Map接口的Set对象
		Set<Map.Entry<Student, Integer>> co = map.entrySet();
		//实例化迭代器
		Iterator<Map.Entry<Student, Integer>> itr = co.iterator();
		//通过迭代器遍历Set集合
		while(itr.hasNext()) {
			//从Iterator中取出Map.Entry对象
			Map.Entry<Student, Integer> me = itr.next();
			System.out.println(me);
		}	
	}
}

输出结果:
在这里插入图片描述
可以看到没有输出异常,但是第二行和第三行的key值是一样的,这就会产生key重复的错误,而HashMap规定key是不能重复的。

如果覆写了hashCode()和equals()方法:

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

//建立一个Student类
class Student{
	private int id;//学号
	private String name;//姓名
	
	//有参构造器
	public Student(int id,String name) {
		this.id = id;
		this.name = name;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	//重写toString方法
	public String toString() {
		return "学号:"+id+","+"姓名:"+name;
	}
}

public class Object_Key {
	public static void main(String[] args) {
		//实例化Map对象,Student-key,Integer-values
		Map<Student,Integer> map = new HashMap<>();
		
		//在Map集合中加入元素
		map.put(new Student(1001,"张三"),1);
		map.put(new Student(1001,"张三"),2);
		map.put(new Student(1003,"李四"),3);
		map.put(new Student(1004,"王五"),4);
		
		//获得Map接口的Set对象
		Set<Map.Entry<Student, Integer>> co = map.entrySet();
		//实例化迭代器
		Iterator<Map.Entry<Student, Integer>> itr = co.iterator();
		//通过迭代器遍历Set集合
		while(itr.hasNext()) {
			//从Iterator中取出Map.Entry对象
			Map.Entry<Student, Integer> me = itr.next();
			System.out.println(me);
		}	
	}
}

输出结果:
在这里插入图片描述
当put()时,因为hashCode()和equals()方法的覆写第二个覆盖了第一个。
所以输出的结果中就会没有相同的key值了。


总结:
A:自定义对象,作为value放入HashMap时,无需考虑hashCode()和equals()方法的覆写。
B:自定义对象,作为key放入HashMap时,一定要覆写hashCode()和equals()方法。
注意:
1)hashCode()相等,对象不一定equals();对象equals(),hashCode()一定相等。
2)HashMap table[]默认值为16;允许空key,空value。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值