爲什麼Hash類容器,放入的元素必須複寫hashCode()方法和equals()方法?

**

爲什麼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。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章