不是说hashset对元素的存储是无序的吗?那为什么输出是有序的?

五维浪人 2019-10-15 03:16:59

...全文
600 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
yuyishui 2019-10-16
  • 打赏
  • 举报
回复
无序指的是你遍历时不保证输出的顺序=输入的顺序 换String输入试试看
编程写手 2019-10-16
  • 打赏
  • 举报
回复
你使用的是int类型,本身哈希值就是数值,然后结果就是有序的
阿发你好 2019-10-15
  • 打赏
  • 举报
回复
无序的意思不保证顺序。。
maradona1984 2019-10-15
  • 打赏
  • 举报
回复
Integer的hashCode就是数字本身,HashSet其实用的是HashMap的实现,下标是根据hashCode算出来的 (h = key.hashCode()) ^ (h >>> 16),低于2的16次方的数字hash的结果还是自身,你的测试只能说明你的数字太小
yety123 2019-10-15
  • 打赏
  • 举报
回复
https://blog.csdn.net/qq_24251323/article/details/52748398 参考博文
烫炒栗子 2019-10-15
  • 打赏
  • 举报
回复
import java.util.HashSet; public class HashTableTest { public static void main(String[] args) { HashSet<Integer> set = new HashSet<Integer>(); for (int i = 1; i < 12; i++) { set.add(i); } set.add(17); System.out.println(set); System.out.println(hash(17)); } /* set.add()方法其实在底层最终是调用了一个hash方法,此方法是对数据的hashcode进行处理,然后返回一个整数,这个数最终就是在set集合中存储的位置 */ static final int hash(Object key) { //此方法对数据的hashcode进行处理 int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } } 运行结果为: [1, 17, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] 17 通过上面的代码可以看出,set 的存储确实是无序的,那么为什么楼主的30个数字全都是有序输出呢,我们可以根据set的存储原理来分析一下。 首先要知道Hash表是由数组和链表来进行数据存储的,默认情况下数组长度是16(这个长度是动态变化的),当里面的数据超过阈值的时候(当前数组的0.75倍),数组就会自动的增加或减少(增加或减少的数值为2的倍数) import java.util.HashSet; public class HashTableTest { public static void main(String[] args) { // HashSet<Integer> set = new HashSet<Integer>(); // for (int i = 0; i < 11; i++) { // set.add(i); // } // set.add(17); // System.out.println(set); // System.out.println(hash(17)); for(int i = 1; i<12;i++){ System.out.print(hash(i) + ","); } System.out.print(hash(17)); } static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } } 运行结果为: 1,2,3,4,5,6,7,8,9,10,11,12,17 首先我先输出一下这12个数字经过hash方法处理过的结果,这就是每个数字所对应的最终在内部存储的位置,首先添加第一个数据1,那么这个数字和hash方法处理过返回的数字相同,那么底层就用这个1%16(数组默认为16)得到的余数为1,那么就会将1存进索引为1的数组中,,同理类推2就会存入索引为2的数组中,那么到了17的时候得到的余数为1,就会存入到索引为1的数组中。如图1所示: 那么当我们继续往里面添加一个数字12的时候(代码在下面),经过hash方法的计算,整数12的这个返回值也是12,(其实10000以前的数值包括后面的一些整数返回来的值都是本身,当你查询99999的时候返回值就不是本身了)那么我们前面说过当数据超过阈值的时候(默认值16*0.75 = 12)数组就会增加2的倍数变为32,此时数据在集合内部的存入位置就会发生改变。如下图2所示: 那么当set遍历的时候就会从索引1的位置开始遍历一直到最后的17结束,这里的17是因为数组的长度发生了变化,从16变为32,所以17%32的余数为17,位置就发生了变化 import java.util.HashSet; public class HashTableTest { public static void main(String[] args) { HashSet<Integer> set = new HashSet<Integer>(); for (int i = 1; i < 13; i++) { set.add(i); } set.add(17); System.out.println(set); System.out.println(hash(17)); // for(int i = 1; i<13;i++){ // System.out.print(hash(i) + ","); // } // System.out.print(hash(17)); } static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } } 运行结果为: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 17] 17 此时数组长度为32,32*0.75=24,也就是说当我们从1添加到24的时候,他的输出顺序都是有序的 运行结果: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] 当你在往里面继续添加数字25的时候数组的长度又超过阈值,此时数组长度会自动变为128,128*0.75=96‬那么这时候你往里面存入1-96的时候输出是都是按照顺序输出的。可自行测试。

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧