一、概述
java.util.HashSet 是 Set 接口的一個實現類,它所存儲的元素是不可重復的,並且元素都是無序的(即存取順序不一致)。
java.util.HashSet 底層的實現是一個 java.util.HashMap 支持。
HashSet 是根據對象的哈希值來確定元素在集合中的存儲位置,因此具有良好的存儲區和查找性能。保證元素唯一性的方式依賴於:hashCode 與 equals 方法。
特點:
1. 不允許存儲重復的元素
2. 沒有索引,也沒有帶索引的方法,不能使用普通 for 循環遍歷
3. 是一個無序的集合,存儲元素和取出元素的順序有可能不一致
4. 底層是一個哈希表結構(查詢的速度非常的快)
二、HashSet 集合存儲數據的結構
1、哈希值
哈希值:是一個十進制的整數,由系統隨機給出(就是對象的地址值,是一個邏輯地址,是模擬出來得到地址,不是數據實際存儲的物理地址)
在 Object 類中有一個方法,可以獲取對象的哈希值。
int hashCode() 返回該對象的哈希碼值。
hashCode 方法的源碼:
public native int hashCode();
native:代表該方法調用的是本地操作系統的方法
2、哈希表
在 JDK1.8 之前,哈希表底層采用數組+鏈表實現,即使用鏈表處理沖突,同一hash值的鏈表都存儲在一個鏈表里。但是當位於一個桶中的元素較多,即hash值相等的元素較多時,通過key值依次查找的效率較低。
JDK1.8中(之后),哈希表存儲采用數組+鏈表+紅黑樹實現,當鏈表長度超過閾值(8)時,將鏈表轉換為紅黑樹,這樣大大減少了查找時間。
存儲流程圖:
Demo:
3、Set 集合不允許存儲重復元素的原理
三、HashSet 存儲自定義類型元素
給HashSet中存放自定義類型元素時,需要重寫對象中的hashCode和equals方法,建立自己的比較方式,才能保證HashSet集合中的對象唯一。
Demo:

1 // 創建自定義 student 類 2 public class Student { 3 private String name; 4 private int age; 5 6 public Student() { 7 } 8 9 public Student(String name, int age) { 10 this.name = name; 11 this.age = age; 12 } 13 14 public String getName() { 15 return name; 16 } 17 18 public void setName(String name) { 19 this.name = name; 20 } 21 22 public int getAge() { 23 return age; 24 } 25 26 public void setAge(int age) { 27 this.age = age; 28 } 29 30 @Override 31 public boolean equals(Object o) { 32 if (this == o) 33 return true; 34 if (o == null || getClass() != o.getClass()) 35 return false; 36 Student student = (Student) o; 37 return age == student.age && 38 Objects.equals(name, student.name); 39 } 40 41 @Override 42 public int hashCode() { 43 return Objects.hash(name, age); 44 } 45 } 46 // 創建測試類 47 public class HashSetDemo2 { 48 public static void main(String[] args) { 49 //創建集合對象 該集合中存儲 Student類型對象 50 HashSet<Student> stuSet = new HashSet<Student>(); 51 //存儲 52 Student stu = new Student("於謙", 43); 53 stuSet.add(stu); 54 stuSet.add(new Student("郭德綱", 44)); 55 stuSet.add(new Student("於謙", 43)); 56 stuSet.add(new Student("郭麒麟", 23)); 57 stuSet.add(stu); 58 59 for (Student stu2 : stuSet) { 60 System.out.println(stu2); 61 } 62 } 63 } 64 執行結果: 65 Student [name=郭德綱, age=44] 66 Student [name=於謙, age=43] 67 Student [name=郭麒麟, age=23]
四、遍歷集合
1、增強 for 循環
for (Integer i : set) {
System.out.println(i);
}
2、迭代器遍歷
Iterator<Integer> it = set.iterator();
while (it.hasNext()){
Integer n = it.next();
System.out.println(n);
}