HashSet的存储分析
一、问题的发现:(以下代码可直接复制测试)在做斗地主洗牌的时候我们发现在一个新的HasSet中添加1-52,打印HasSet时输出也是1-52
Set hashSet = new HashSet();
for (int i = 1; i <= 52; i++) {
hashSet.add(i);
}
System.out.println(hashSet);//
二、问题的提出:
问题1.不是说HashSet是无序吗?
解:HashSet的无序是体现在''存放''的顺序和''取出''的顺序可能会不一样;
Set hashSet = new HashSet();
hashSet .add(3);
hashSet .add(2);
hashSet .add(17);
System.out.println(hashSet);//
看这就无序了,那为什么会这样呢
问题2.HashSet到底是如何存放数据的?
第一步:我们得先看一下HashSet的数据结构是什么样子的;
在jdk1.8之前:HashSet结构=数组结构+链表结构;
在jdk1.8之后包括1.8:HashSet结构=数组结构+链表结构;
HashSet结构=数组结构+红黑树结构(当链表长度>=8);
第二步:
每次数据存放的位置是:()数据的hasCode()值) 取余(数组长度 )=余数,该余数就是放在数组对应的索引上面
2.1:那万一余数相同怎么办?
如果没有重写equals()方法:则比较地址值,地址值相同则不存;否则以链表的形式存取
如果重写了equals()方法:则比较内容值,内容值相同则不存;否则以链表的形式存取
2.2:那初始的数组长度是多少?
新建的HashSet初始数组长度是2*4=16;
每当hasSet.length>数组长度*0.75时,为保证能存下所有数据数组的长度会翻一倍2*5=32,HashSet的数据结构会重建,之后再刚刚提到的方式进行数据重新排序;
3.3:那hashCode()值如何计算?
调用hashCode()方法打印就可以看到;
String类源码较为复杂(我也没看懂)总结为:
public static int getStringHasCode(String str){
char[] chars = str.toCharArray();//{0,0}
int hasCode = 0;
for (int i = 0; i < chars.length; i++) {
hasCode = 31*hasCode + chars;//48,48*31+48
}
return hasCode;
}
本帖最后由 cx1521126332 于 2019-2-22 17:32 编辑
HashSet存取数据流程.png 本帖最后由 cx1521126332 于 2019-2-22 17:32 编辑
HasSet的数据结构.png {:10_265:} 鱼币 鱼币 鱼币 {:10_269:} 学习 学习 学习学习{:10_256:}{:10_256:}{:10_256:} 学习 {:10_279:} {:10_266:} 没有 {:10_256:} {:10_260:} {:10_258:} 没有了 {:10_261:}