本文主要是介绍java-hashset随机数字放入后大小排序的假象,以及数字大小与数字范围的关系。,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
起因
首先是因为thinking in java的一个例子(一个存放int的set集合):
但是与他期待的output不一致:
出现了从小到大的顺序排列输出。
仔细看看果然没什么差别(网上看到原因是jdk版本不一致,hashmap的hash算法不一致)
在网上找到了存放数据的原理:
简要概括就是因为hashset里面存放的是hashmap,数字是放进了hashmap的entry的key之中。如何遍历是通过迭代器,迭代器遍历的其实是key的迭代对象,也就是遍历了一遍hashmap的key。
public Iterator<E> 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就是一到十,所以从头开始遍历就是那个从小到大的顺序。
但是发生了奇怪的事情:
一百个数字的时候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。
3
4
133 % 128 = 5
134 % 128 = 6
7
9
10 (138 % 128 = 10)碰撞了。
有高人理解可以留言交流。
这篇关于java-hashset随机数字放入后大小排序的假象,以及数字大小与数字范围的关系。的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!