Java HashSet 的 无序和乱序

HashSet 无序、乱序问题

(1)定义
HashSet:一种没有重复元素的无序集合
解释:我们一般说HashSet是无序的,它既不能保证存储和取出顺序一致,更不能保证自然顺序(a-z)
数据结构:HashSet底层是HashMap
源码在new HashSet() 的时候,实际上是创建了一个HashMap实例对象

public HashSet() {
        map = new HashMap<>();
    }

(2)过程
通过一步一步分析源码,我们来看一看,这究竟是怎么一回事,首先我们先从程序的第一步——集合元素的存储开始看起,先看一看HashSet的add方法源码:

// HashSet 源码节选-JKD8
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
我们可以看到,HashSet直接调用HashMap的put方法,并且将元素e放到map的key位置(保证了唯一性 )

顺着线索继续查看HashMap的put方法源码:

//HashMap 源码节选-JDK8

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

而我们的值在返回前需要经过HashMap中的hash方法

接着定位到hash方法的源码:

//HashMap 源码节选-JDK8

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

hash方法的返回结果中是一句三目运算符,键 (key) 为null即返回 0,存在则返回后一句的内容

(h = key.hashCode()) ^ (h >>> 16)
JDK8中 HashMap——hash 方法中的这段代码叫做 “扰动函数”

从上面能了解到key.hashCode()是hash()计算的一个核心的函数,这个key,就是你放到set里面的对象。所以在不重新set里面对象的hashCode方法前,一次往set里面放数据再取出里是无序的,但之后再方数据,无论多少次,取出来的顺序都是与第一次取的顺序相同。

(3)应用
想用HashSet做乱序操作,可以把Set里面的对象的hashCode方法重写了,让他是随机的,每一次调用都不是同一个值,这样再map里面的put通过hash(key)确定位置的时候就能做到每次都不一样了

(4)例子
在这里插入图片描述
红框是重点,这样每次调用Objects.hash方法的时候,计算出来的code是不一样的

在这里插入图片描述
在这里插入图片描述
这是第一次
在这里插入图片描述
这是第二次

反例
在这里插入图片描述
把hashCode放注释掉
结果
在这里插入图片描述
第一次
在这里插入图片描述
第二次
由此验证看出,重写key的hashCode方法能做到set每次存放乱序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值