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計算公式