Set集合

Set集合

  1. HashSet的2中遍歷方式

    • 執行路口

      package cn.xiaoge.day14.demo02;
      
      /*
          java.util.Set接口 extends Collection接口
          Set接口的特點:
              1. 不允許存儲重複的元素
              2. 沒有索引, 沒有帶索引的方法, 也不能使用普通的for循環遍歷
          java.util.HashSet集合 implements Set接口
          HashSet特點:
              1. 不允許存儲重複的元素
              2. 沒有索引, 沒有帶索引的方法, 也不能使用普通的for循環遍歷
              3. 是一個無序的集合, 存儲元素和取出元素的順序有可能不一致
              4. 底層是一個哈希表結構(查詢的速度非常的塊)
       */
      
      import java.util.HashSet;
      import java.util.Iterator;
      import java.util.Set;
      
      public class Demo01Set {
      
          public static void main(String[] args) {
              Set<Integer> set = new HashSet<>();
              // 使用add方法往集合中添加元素
              set.add(1);
              set.add(3);
              set.add(2);
              set.add(1);
      
      
              // 使用迭代器遍歷set集合
              Iterator<Integer> it = set.iterator();
              while(it.hasNext()){
                  System.out.println(it.next()); // 1, 2, 3
              }
              System.out.println("===================");
      
      
              // 使用增強for循環遍歷set集合
              for (int num: set) {
                  System.out.println(num); // 1, 2, 3
              }
          }
      
      }
      
      // 運行結果
      1
      2
      3
      ===================
      1
      2
      3
      
  2. HashSet存儲不重複元素的原理

    • 執行路口

      package cn.xiaoge.day14.demo02;
      
      /*
          Set集合不允許存儲重複元素的原理
      
          Set集合在調用add方法的時候, add方法會調用元素的hashCode方法和equals方法, 判斷元素是否重複.
      
          set.add(s1);
          add方法會調用hashCode方法, 計算字符串"abc"的哈希值, 哈希值是**96354**在集合中找有沒有**96354**
          這個哈希值的元素, 發現**沒有**, **就會把s1存儲到集合中**
      
          set.add(s2);
          add方法會調用s2的hashCode方法, 計算字符串"abc"的哈希值, 哈希值是**96354**在集合中找有沒有**96354**
          這個哈希值的元素, 發現**有(哈希衝突)**, s2會調用equals方法和哈希值相同的元素進行比較s2.equals(s1), 返回
          **true**兩個元素的哈希值相同, equals方法返回true, 認定**兩個元素相同*, 就不會把s2存儲到集合中**
      
          set.add("重地");
          set.add("通話");
          哈希值相同, 值不相同所以存儲
      
          set.add("abc");
          哈希值相同, 值相同不存儲
       */
      
      import java.util.HashSet;
      
      public class Demo02HashSetSaveString {
      
          public static void main(String[] args) {
              // 創建HashSet集合對象
              HashSet<String> set = new HashSet<>();
              String s1 = new String("abc");
              String s2 = new String("abc");
              set.add(s1);
              set.add(s2);
              set.add("重地");
              set.add("通話");
              set.add("abc");
              System.out.println(set); // [重地, 通話, abc]
      
          }
      
      }
      
      // 運行結果
      [重地, 通話, abc]
      
  3. 哈希值

    • Person類

      package cn.xiaoge.day14.demo03;
      
      public class Person extends Object {
          // 重寫hashCode方法
          @Override
          public int hashCode(){
              return 1;
          }
      }
      
      
    • 執行路口

      package cn.xiaoge.day14.demo03;
      
      /*
          哈希值: 是一個十進制的整數, 由系統隨機給出(就是對象的地址值, 是一個邏輯地址, 是模擬出來的地址, 不是數據實際存儲的物理地址)
          在Object類有一個方法, 可以獲取對象的哈希值
          int hashCode() 返回該對象的哈希碼值.
          hashCode方法的源碼:
              public native int hashCode();
              native: 代表該方法調用的是本地操作系統的方法
       */
      
      public class Demo02HashCode {
      
          public static void main(String[] args) {
              // Person類繼承了Object類, 所以可以使用Object類的hashCode方法
              Person p1 = new Person();
              int h1 = p1.hashCode();
              System.out.println(h1); // 1639705018  |  1(重寫後的值)
              System.out.println("===================");
      
              Person p2 = new Person();
              int h2 = p2.hashCode();
              System.out.println(h2); // 1627674070  |  1(重寫後的值)
              System.out.println("===================");
      
      
              /*
                  toString方法的源碼:
                      public String toString() {
                          return getClass().getName() + "@" + Integer.toHexString(hashCode());
                      }
               */
              System.out.println(p1); // cn.xiaoge.day14.demo03.Person@61bbe9ba
              System.out.println(p2); // cn.xiaoge.day14.demo03.Person@610455d6
              System.out.println(p1==p2); // false
              System.out.println("===================");
      
      
              /*
                  String類的哈希值
                      String類重寫Object類的hashCode方法
               */
              String s1 = new String("abc");
              String s2 = new String("abc");
              System.out.println(s1.hashCode()); // 96354
              System.out.println(s2.hashCode()); // 96354
              System.out.println("===================");
      
      
              // 他們兩個字符串雖然不同, 但是這兩個的哈希值確實是一樣的(哈希衝突)
              System.out.println("重地".hashCode()); // 1179395
              System.out.println("通話".hashCode()); // 1179395
      
          }
      
      }
      
      // 運行結果
      1
      ===================
      1
      ===================
      cn.xiaoge.day14.demo03.Person@1
      cn.xiaoge.day14.demo03.Person@1
      false
      ===================
      96354
      96354
      ===================
      1179395
      1179395
      
  4. HashSet存儲自定義元素

    • Person類

      package cn.xiaoge.day14.demo02;
      
      import java.util.Objects;
      
      public class Person {
          private String name;
          private int age;
      
          public Person() {
          }
      
          public Person(String name, int age) {
              this.name = name;
              this.age = age;
          }
      
          @Override
          public boolean equals(Object o) {
              if (this == o) return true;
              if (o == null || getClass() != o.getClass()) return false;
              Person person = (Person) o;
              return age == person.age &&
                      Objects.equals(name, person.name);
          }
      
          @Override
          public int hashCode() {
      
              return Objects.hash(name, age);
          }
      
          @Override
          public String toString() {
              return "Person{" +
                      "name='" + name + '\'' +
                      ", age=" + age +
                      '}';
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public int getAge() {
              return age;
          }
      
          public void setAge(int age) {
              this.age = age;
          }
      }
      
    • 執行路口

      package cn.xiaoge.day14.demo02;
      
      /*
          HashSet存儲自定義類型元素
      
          set集合保證元素唯一:
              存儲的元素(String, Integer, ...Student, Person...), 必須重寫hashCode方法和equals方法
      
          要求:
              同名同年齡的人, 視爲同一個人, 只能存儲一次
       */
      
      import java.util.HashSet;
      
      public class Demo03HashSetSaveString {
      
          public static void main(String[] args) {
              // 創建HashSet集合存儲Person
              HashSet<Person> set = new HashSet<>();
              Person p1 = new Person("小美女", 18);
              Person p2 = new Person("小美女", 18);
              Person p3 = new Person("小美女", 19);
      
              // 哈希值
              System.out.println(p1.hashCode()); // 1639705018 | 從寫hashCode方法 734175839
              System.out.println(p2.hashCode()); // 1627674070 | 從寫hashCode方法 734175839
              System.out.println("========================");
              // equals
              System.out.println(p1.equals(p2)); // false  equals比較地址值, 因爲equals是Object類方法 | 從寫了equals方法 true
              set.add(p1);
              set.add(p2);
              set.add(p3);
      
              System.out.println(set); // [Person{name='小美女', age=18}, Person{name='小美女', age=18}, Person{name='小美女', age=19}]  |  [Person{name='小美女', age=19}, Person{name='小美女', age=18}]
          }
      
      }
      
      // 運行結果
      734175839
      734175839
      ========================
      true
      [Person{name='小美女', age=19}, Person{name='小美女', age=18}]
      
  5. LinkedHashSet集合

    • 執行路口

      package cn.xiaoge.day14.Demo04;
      
      /*
          java.util.LinkedHashSet集合 extends HashSet集合
      
          LinkedHashSet集合特點:
              底層是一個哈希表(數組+鏈表/紅黑樹) + 鏈表: 多了一條鏈表(記錄元素的存儲順序), 保證元素有序
       */
      
      import java.util.HashSet;
      import java.util.LinkedHashSet;
      
      public class Demo04LinkedHashSet {
      
          public static void main(String[] args) {
              HashSet<String> set = new HashSet<>();
              set.add("www");
              set.add("abc");
              set.add("abc");
              set.add("xiaoge");
              System.out.println(set); // [abc, www, xiaoge] 無序, 不允許重複
              System.out.println("====================================");
              LinkedHashSet<String> linked = new LinkedHashSet<>();
              linked.add("www");
              linked.add("abc");
              linked.add("abc");
              linked.add("xiaoge");
              System.out.println(linked); // [www, abc, xiaoge] 有序, 不允許重複
          }
      
      }
      
      // 運行結果
      [abc, www, xiaoge]
      ====================================
      [www, abc, xiaoge]
      
發佈了298 篇原創文章 · 獲贊 94 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章