java-hashset随机数字放入后大小排序的假象,以及数字大小与数字范围的关系。

起因

首先是因为thinking in java的一个例子(一个存放int的set集合):
java-hashset随机数字放入后大小排序的假象,以及数字大小与数字范围的关系。_第1张图片
但是与他期待的output不一致:
这里写图片描述
出现了从小到大的顺序排列输出。
仔细看看果然没什么差别(网上看到原因是jdk版本不一致,hashmap的hash算法不一致)

在网上找到了存放数据的原理:

简要概括就是因为hashset里面存放的是hashmap,数字是放进了hashmap的entry的key之中。如何遍历是通过迭代器,迭代器遍历的其实是key的迭代对象,也就是遍历了一遍hashmap的key。

public Iterator iterator() {
        return map.keySet().iterator();
    }

(在jdk8中,hashmap中hash算法对数字的混淆变低)详情请看高票回答:
https://www.zhihu.com/question/28414001/answer/40733996
然后插入的数字被hash算法算了之后就是本身:

    public static int hashCode(int value) {
        return value;
    }

了解hashmap的放入数据的同学应该知道,那个entry数组是根据hashcode排列的,所以比如说是10个数字一到十,那么那个数组的hashcode就是一到十,所以从头开始遍历就是那个从小到大的顺序。

但是发生了奇怪的事情:

java-hashset随机数字放入后大小排序的假象,以及数字大小与数字范围的关系。_第2张图片

java-hashset随机数字放入后大小排序的假象,以及数字大小与数字范围的关系。_第3张图片

一百个数字的时候0-100正常排序但是0-300又是乱了。


个人理解是:是不是可以这样理解,
① 100个100以内的数字正好差不多100大小的数组排好,都是100以内的数字不产生碰撞,
② 但100个300以内的会发生碰撞,然后数组大小扩容到一定程度也放得下,所以数组不会继续扩容。

所以100个300以内的数字,数组长度可能是100/0.75 大概是125左右 因为是从16开始翻倍增长的所以长度应该是128,与下图这个126数字相符。因此我猜测100个数字的长度的数组在hashset内扩容到128就不会扩容了,但是之后放入的数字可能就会碰撞,就像138,然后不会扩容,因此会像下面的数字一样存放。比128大的也可能不碰撞,就像133,134。
java-hashset随机数字放入后大小排序的假象,以及数字大小与数字范围的关系。_第4张图片
3
4
133 % 128 = 5
134 % 128 = 6
7
9
10 (138 % 128 = 10)碰撞了。

有高人理解可以留言交流。

你可能感兴趣的:(后端学习,java8,java基础)