java集合框架之HashSet類

1.Set是Collection子接口

模擬了數學上的集的概念。

-----------------------------------------------------------------------
Set集合存儲特點:
     1):不允許元素重複.
     2):不會記錄元素的先後添加順序.

-----------------------------------------------------------------------

Set只包含從Collection繼承的方法,不過Set無法記住添加的順序不允許包含重複的元素。當試圖添加兩個相同元素進Set集合,添加操作失敗,add()方法返回false。

import java.util.HashSet;
import java.util.Set;

public class SetDemo2 {
	public static void main(String[] args) {
		Set<String> set = new HashSet<>();
		set.add("小明");
		set.add("小紅");
		set.add("小張");
		set.add("小明");//和第一個是同一個對象,所以不能添加
		
		System.out.println(set.size());//3
		System.out.println(set);//打印結果:[小張, 小明, 小紅],不會記錄添加順序
	}
}

Set判斷兩個對象是否相等用equals,而不是使用==。也就是說兩個對象equals比較返回true,Set集合是不會接受這個對象的

HashSet是Set接口最常用的實現類,顧名思義,底層才用了哈希表(散列/hash)算法.
其底層其實也是一個數組,存在的意義是提供查詢速度,插入速度也比較快,但是適用於少量數據的插入操作.

HashSet類是線程不安全的類,在多線程環境下想要保證線程安全.
HashSet set = Collections.synchronizedSet(new HashSet(...));

在HashSet中如何判斷兩個對象是否相同問題:
       1):兩個對象的equals比較相等.   返回true,則說明是相同對象.
       2):兩個對象的hashCode方法返回值相等.

對象的hashCode值決定了在哈希表中的存儲位置.
二者:缺一不可.
當往HashSet集合中添加新的對象的時候,先回判斷該對象和集合對象中的hashCode值:
                         1):不等: 直接把該新的對象存儲到hashCode指定的位置.
                         2):相等: 再繼續判斷新對象和集合對象中的equals做比較.
                                        1>:hashCode相同,equals爲true: 則視爲是同一個對象,則不保存在哈希表中.
                                        1>:hashCode相同,equals爲false:非常麻煩,存儲在之前對象同槽爲的鏈表上(拒絕,操作比較麻煩).



對象的hashCode和equals方法的重要性:
每一個存儲到hash表中的對象,都得提供hashCode和equals方法,用來判斷是否是同一個對象.
存儲在哈希表中的對象,都應該覆蓋equals方法和hashCode方法,並且保證equals相等的時候,hashCode也應該相等.通過源碼可以看到,String類,Integer等8大基本類型包裝類都已經覆蓋equals方法和hashCode方法,有了自己的判斷方式,所以可以直接使用.

如果需要把我們自定義的對象存儲到哈希表中,該類型的對象應該覆蓋equals和hashCode方法,並在該方法中提供自己的判斷規則.可以使用Eclipse工具自動生成hashCode和equals方法.





生成之後就是下面這樣:

class Person{
	private int id;
	private int age;
	private String name;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (id != other.id)
			return false;
		return true;
	}
}

你可以根據自己的需求來選擇判斷的條件

舉個例子:我們就根據id來決定Person是同一個對象,根據上面的步驟生成根據id來判斷的hashCode和equals方法,然後測試添加,注意,Set集合是根據這兩個方法一起來判斷的,缺一不可

import java.util.HashSet;
import java.util.Set;
//Person類
class Person{
	private int id;
	private int age;
	private String name;
	
	public Person() {
		super();
	}
	public Person(int id, int age, String name) {
		super();
		this.id = id;
		this.age = age;
		this.name = name;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}	
	@Override
	public String toString() {
		return "Person [id=" + id + ", age=" + age + ", name=" + name + "]";
	}
	
	//hashCode方法
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}
	//equals方法
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (id != other.id)
			return false;
		return true;
	}
}
//測試類
public class SetDemo1 {
	public static void main(String[] args) {
		Person p1 = new Person(0, 18, "張三");
		Person p2 = new Person(1, 18, "李四");//與p1相比年齡相同,姓名,id不同
		Person p3 = new Person(2, 19, "張三");//與p1相比姓名相同,年齡,id不同
		Person p4 = new Person(3, 18, "張三");//與p1相比年齡和姓名都相同,但是id不同
		Person p5 = new Person(0, 19, "王五");//與p1相比id相同,只要id相同就是同一個對象,上面我們已經定義了
		
		Set<Person> set = new HashSet<>();
		set.add(p1);
		set.add(p2);
		set.add(p3);
		set.add(p4);
		set.add(p5);//添加失敗,因爲是同一個對象
		
		System.out.println(set.size());//只添加了4個,因爲第5個和第一個相同
		System.out.println(set);//打印結果[Person [id=3, age=18, name=張三], Person [id=1, age=18, name=李四], Person [id=2, age=19, name=張三], Person [id=0, age=18, name=張三]]
		//可以看到打印結果跟添加順序不一樣,說明Set集合不會記錄添加順序
	}
}

對象的hashCode計算公式




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