简介

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

特点:

  • 不允许存储重复的元素
  • 没有索引,不能使用普通的for循环遍历。(可以使用增强for和迭代器遍历)
  • 一个无序的集合,存储元素和取出元素的顺序不一致
  • 底层是一个哈希表结构(查询的速度非常快)

 哈希值

哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到的地址,不是实际的物理地址)。在Object 类有一个方法,可以获取对象的哈希值。int hashCode()返回对象的哈希码值。

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

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

set集合存储元素不重复的原理

当我们使用set中的add方法添加元素的时候,add方法会调用要添加的元素的hashCode方法,计算元素的哈希值。之在集合中寻找有没有重复的哈希值,没有则添加元素进入set集合。如果有,则要添加元素会调用equals方法,比较2个哈希值相同的元素,如果equals方法的返回值为true,则判断两个元素相同,要添加的元素不会存储到集合中。如果equals方法返回值为false,则会添加到元素中。

总结: JDK1.8引入红黑树大程度优化了HashMap的性能,那么对于我们来讲保证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。 如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。 代码举例:
package demo03;

import java.util.Objects;

public class Person {
    // 成员变量
    private String name;

    //无构造
    public Person() {
    }

    //全参数构造
    public Person(String name) {
        this.name = name;
    }
    //重写toString

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }

    //get /set方法

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    // 重写hashCode 和equals方法

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

    @Override
    public int hashCode() {

        return Objects.hash(name);
    }
}

定义HashSet集合

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
package demo03;

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

public class HashSetTest {
    public static void main(String[] args) {
        // 多态,创建子类对象
        Set<Person> set = new HashSet<>();
        //添加自定义对象
        set.add(new Person("张三"));
        set.add(new Person("李四"));
        set.add(new Person("张三"));
        set.add(new Person("王五"));

        //遍历集合
        for (Person person : set) {
            // 获取每个对象的
            System.out.println(person);
        }


    }
}

执行结果

 类HashSet 随笔

 

 

 

       
扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄