怀旧网,博客详情:Java HashSet 介绍

1、java枚举类详解

2、java String 类和类方法详解

3、StringBuffer 详解

4、Java Math 类详解

5、java random详解

6、java Date类使用讲解

7、java 集合类详解

8、java算法二分查找

9、SpringBoot 在初始化加载无法使用@Value的时候读取配置文件教程

10、springboot 项目配置本地jar包导入

11、单个java文件运行需要带上jar包的用法

12、spring boot 项目配置https服务

13、Java异常详解

14、Java Collection的使用

15、Java List 集合

16、Java ArrayList 介绍

17、Java LinkedList 讲解

18、Java Set 集合介绍

19、Java HashSet 介绍

20、Java TreeSet 介绍

21、Java Map 介绍以及子类介绍

22、Java 多线程使用介绍

23、Java 注解讲解

24、Java 反射讲解

25、Java 反射讲解

26、HashMap 源码讲解

27、面向对象初级教学

28、Java整合JWT使用

原创

Java HashSet 介绍

哈希值介绍

创建一个实体类

public class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

使用测试

public static void main(String[] args) {
    Student s1 = new Student("zhangsan", 12);
    Student s2 = new Student("zhangsan", 12);

    System.out.println(s1.hashCode());
    System.out.println(s2.hashCode());
}

image-20240315164034665

  • 打印结果不同

重写hashCode 和 equals方法后

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Student student = (Student) o;
    return age == student.age && Objects.equals(name, student.name);
}

@Override
public int hashCode() {
    return Objects.hash(name, age);
}

image-20240315164150805

  • 运行结果相同--自定义类型对象,因为在没有重写hashCode和equals方法前的哈希值是通过地址值来进行计算的。
System.out.println("123".hashCode());
System.out.println("123".hashCode());

image-20240315164415585

  • 测试自定义的String对象时,哈希值相同,说明它重写了hashCode和equals方法。

image-20240315164508997

注意事项:因为哈希值是采用int类型存储,所以哈希值是有限的数据,所以就有可能存在哈希冲突,如下例:

System.out.println("abc".hashCode());
System.out.println("acD".hashCode());

image-20240315194102152

HashSet 的底层原理

HashSet 的底层构成

image-20240315194824806

image-20240315195208196

注意事项:

  1. 默认情况下会 new 一个哈希表

image-20240315200305103

  1. 在HashMap中就是采用的内部定义的Node来存放每一个元素

    image-20240316145915007

  • 所以在HashSet中其实主要存的就是HashMap对象,像知道底层的原理,可以看后面的HashMap底层原理介绍。

  • 在调用HashSet的很多方法的时候,其实底层就是去掉了HashMap的方法。

image-20240316150215953

image-20240316150228763

HashSet 的元素添加过程

  1. 首先获取当前需要添加的元素的Hash值

  2. 然后判断当前需要存放的位置是否已经有元素了

  3. 要是没有元素,那就直接将当前添加的元素放到这个位置

  4. 要是有元素了,那就需要对当前存放的数据进行比较判断

  5. 当现在加入的元素在里面的时候,就直接不进行操作,返回false添加失败

  6. 当里面没有时

    • 在Jdk8以前是需要将当前的元素作为头节点,然后将后面的节点连接到当前的节点的下方
    • 在Jdk8及以后是直接将当前元素的尾节点位置,并且当当前的元素数量到达一个阈值后(链表的长度超过8,而且数组的长度大于等于64时),就会自动的将当前的链表转为一颗红黑树来进行存储,而Jdk8以前没有当前的这一步转成红黑树的操作。
  7. 成功将当前数据存储后直接返回true添加元素成功。

HashSet 的三个特点介绍

HashSet 无序的特点

  • 因为HashSet底层还是使用的数组来进行数据存储的,在取数据的时候,它是从小标为0的数组位置依次进行取数据
  • 而我们在存数据的时候,我们是通过计算出的Hash值来判断具体存在那个下标位置的
  • 所以导致我们先存的数据可能存储的下标位置在后面,然后就导致HashSet是无序的
public static void main(String[] args) {
    HashSet<String> set = new HashSet<>();

    set.add("123");
    set.add("456");
    set.add("444");

    System.out.println(set);
}

image-20240316151604324

HashSet 没有索引

  • 因为在底层存储的数据中,每一个下标位置存的是一串链表,或者是一颗红黑树,所以通过下标访问,就不能够有效的取出某一个数据

HashSet 的去重机制

  • 主要其实就是通过HashCode方法和equals方法来进行的
  • 当计算出添加的元素的Hash地址后就可以知道当前需要添加的元素需要存放的位置
  • 然后在通过equals方法来判断当前的元素值是否一样,要是也想通,那么就说明当前的数据重复,从而达到去重效果

扩展 LinkedHashSet 介绍

特点

  • 和HashSet的不同之处---LinkedHashSet在做取的时候,得到的属于是有序的。

有序的原理

  • 它是在底层的HashSet基础之上添加一个指针来记录当前添加进来的第一个元素,作为当前链表的头节点
  • 然后在第二个元素进来后,就会将第二个元素和第一个元素之间相互连接,并且第二个元素会被链表的尾指针指向
  • 在实际调用遍历方法的时候,和HashSet的区别就是,前者是遍历每一个列表元素,而LinkedHashSet是通过头指针,找到第一个元素,然后直接遍历整个链表来实现遍历的。

使用测试

public static void main(String[] args) {
    HashSet<String> set = new HashSet<>();

    set.add("123");
    set.add("456");
    set.add("444");

    System.out.println(set);
}		

image-20240316153002580

  • 使用HashSet的输出结果
public static void main(String[] args) {
    LinkedHashSet<String> set = new LinkedHashSet<>();

    set.add("123");
    set.add("456");
    set.add("444");

    System.out.println(set);
}

image-20240316153045042

  • 通过同样的例子,可以明显看出二者之间的区别

LinkedHashSet 总结

image-20240316153206583

使用场景

image-20240316153230510

  • 平台作者:怀旧(联系作者)
  • QQ:444915368
  • 邮箱:444915368@qq.com
  • 电话:17623747368
  • 评论

    登录后才可以进行评论哦!

    回到顶部 留言