hashset实现原理_Java_HashSet存储数据的结构(哈希表)

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

import java.util.HashSet; //存在util包内,要导包,

哈希值:一个十进制的整数,由系统给出,是一个逻辑地址,并非实际的物理地址

jak1.8版本之前:哈希表=数组+链表

jdk1.8版本之后:

哈希表=数组+链表

哈希表=数组+红黑树(查询速度极快)

哈希表的特点是速度快

当有数据要存储到集合的时候,会先计算元素的哈希值(元素在数组中的存储位置)

HashSet是Set接口的一个实现类,Set接口是Collection类的子类

HashSet集合的其他特点:

哈希表是无序的,而且没有索引,所以只可以用迭代和增强for来遍历
存入的元素不能重复
底层是哈希表结构

HashSet

为什么说存入的元素不能重复:

原理:

在Object类里面有一个 native hashCode();方法可以返回对象的哈希值,在要存储元素之的时候即进行add();方法,add方法会调用hashCode方法和equals方法判断元素是否重复。

例子如下:

5e130471d622954aa1551f96189ff1a4.png
hashSet存储的原理

在这个例子里面

Set集合在调用add方法的时候它会调用元素的HashCode()方法和equals()方法判断元素是否重复
add方法调用s1的hashCode方法计算字符串"abc"的哈希值 96354
在集合里面没有96354就把这个哈希值存入到数组中且把s1字符串挂到这个数组对应的索引下面
add调用s2的hashCode方法计算哈希值,发现数组存在了96354这个哈希值,就会发生哈希冲突,然后调用equals方法s2.equals(s1)
返回ture 两个元素哈希值相同且认定两个元素相同,,就不会把s2存储到集合中
可以同时存入重地和通话完全是因为 在第二步中 重地.equals("通话")不相等返回了false 从而认定元素不相同
发现hash冲突才会调用equals方法

代码如下 :

import java.util.HashSet;

public class Demo03HashSetSaveString {
    public static void main(String[] args) {
        HashSet<String> set=new HashSet<>();//创建一个HashSet对象,不能够多态
        String s1=new String("abc");
        String s2=new String("abc");
        set.add(s1);
        set.add(s2);
        set.add("重地");
        set.add("通话");
        set.add("abc");
        for(String a:set){
            System.out.println(a);


        }
    }
}

这里面要特别提醒:字符串里面 “重地”和“通话”的哈希值是一样的

下图为一个HashSet数组的结构和三个元素,演示存储的过程

f48f33da24574a82f98cb90c8f9a0d84.png

首先存入字符串“abc”;通过hashCode方法发现数组里没有96354这个哈希值,将这个哈希值存入数组,然后将元素"abc"以链表的方式连接在对应的哈希值数组下

v2-d1b5d22425f342000d7215fdda690ea2_b.jpg

然后重复操作同样存入元素"重地";

ab8669f47876f876b1ac8e4fc2dd4434.png
存入“重地”

最后,存入元素“通话”,在调用方法hashCode返回哈希值的时候,发现数组中已经存在117935这个哈希值,要调用equals方法比较元素“重地”和“通话”,若返回false,存入“通话”,若返回ture,放弃存储。很明显,“通话”.equals("重地")返回false,因为哈希值一样所以“通话”以链表的形式挂在“重地”下面,形成链表

08e087a93da009de7a4a12da466b3604.png

哈希表=数组+红黑树(查询速度极快)又是怎么回事呢?

这是当如果表中同一哈希值下挂的元素超过8个就会转换成对应的红黑树(这样查询的速度就超级快)

这就是我所认识的HashSet希望对你有帮助

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值