类HashSet

Posted wurengen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了类HashSet相关的知识,希望对你有一定的参考价值。

 HashSet集合介绍

java.util.HashSet 是 Set 接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致)java.util.HashSet 底层的实现其实是一个 java.util.HashMap 支持。HashSet 是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于: hashCode 与 equals 方法。

什么是哈希值?

就是对象在JVM虚拟出来的内存地址,不是实际物理内存地址。任何类均为Object类的间接子类,所以均继承方法public int hashCode()
该方法返回的值一般是通过将该对象的内部地址转换成一个十进制整数来表现的。这样能保证每个对象的哈希值不一样。

HashSet集合存储数据的结构(哈希表)

  • 在JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。
  • JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。

HashSet存储元素不重复的原理

JVM当需要一个HashSet集合中存储一个元素的时候,先会调用hashCode方法比较此元素的哈希码值是在集合中存在,如果不存在就存入集合中去。如果存在,则调用equals方法比较2个哈希码值相同的元素。equals的返回值为true,则判断为同一个元素,此元素不在存储,如果为false,则存储进入到集合中去。

HashSet存储自定义类型元素

给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一
package demo02;

import java.util.Objects;

public class Student {
    private String name;
    private int 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;
    }

    public Student() {
    }

    public Student(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;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {

        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "Student{" +
                "name=‘" + name + ‘\‘‘ +
                ", age=" + age +
                ‘}‘;
    }
}

测试类

package demo02;

import java.util.HashSet;
import java.util.Set;

public class Test {
    public static void main(String[] args) {
        //多态创建集合,泛型为Student
        Set<Student> set = new HashSet<>();
        // 添加元素
        set.add(new Student("张安1", 18));
        set.add(new Student("张安2", 18));
        set.add(new Student("张安1", 18));
        set.add(new Student("张安2", 19));
        // 查看set集合中的元素
        System.out.println(set);//[Student{name=‘张安1‘, age=18}, Student{name=‘张安2‘, age=19}, Student{name=‘张安2‘, age=18}]

    }
}

LinkedHashSet

我们知道HashSet保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序,怎么办呢?在HashSet下面有一个子类 java.util.LinkedHashSet ,它是链表和哈希表组合的一个数据存储结构。

以上是关于类HashSet的主要内容,如果未能解决你的问题,请参考以下文章

Java提高篇——通过分析 JDK 源代码研究 Hash 存储机制

java中HashMap详解

类HashSet

Java学习笔记5.3.1 Set接口 - HashSet类

跟王老师学集合:Set接口和HashSet类

HashSet——add remove contains方法底层代码分析(hashCode equals 方法的重写)