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]
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只因为你温柔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值