Java 之 HashSet 集合


一、概述

  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:

 

  JDK1.8引入紅黑樹大程度優化了HashMap的性能,那么對於我們來講保證HashSet集合元素的唯一,其實就是根據對象的hashCode和equals方法來決定的。如果我們往集合中存放自定義的對象,那么保證其唯一,就必須復寫hashCode和equals方法建立屬於當前對象的比較方式。

  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]
View Code

 

四、遍歷集合

  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); 
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM