不是说hashset对元素的存储是无序的吗?那为什么输出是有序的? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 https://blog.csdn.net/qq_24251323/article/details/52748398 参考博文 Integer的hashCode就是数字本身,HashSet其实用的是HashMap的实现,下标是根据hashCode算出来的(h = key.hashCode()) ^ (h >>> 16),低于2的16次方的数字hash的结果还是自身,你的测试只能说明你的数字太小 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的时候输出是都是按照顺序输出的。可自行测试。 你使用的是int类型,本身哈希值就是数值,然后结果就是有序的 无序指的是你遍历时不保证输出的顺序=输入的顺序换String输入试试看 支个招:关于Java与C#通过socket通信时的参数传递问题。 java 的小问题 求大虾帮忙 怎样获取mp3文件的播放时间? 是否都有必要设置conn.setAutoCommit(false) 那位帮忙看下这个程序!谢谢啦 高手请进 急急 在线等待 环境变量到底该如何配置,查了不少资料,看了不少的网站,到自已做时,总是有问,搞后后,别给100分。版主能帮帮吗? 问个很基础的问题! 在线等。。。。 java如何控制打印机 j2se 1.4.1 Beta NOW AVAILABLE! 关于java配置的安装,请大佬解答?? Java swing的问题!
(h = key.hashCode()) ^ (h >>> 16),低于2的16次方的数字hash的结果还是自身,你的测试只能说明你的数字太小
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的时候输出是都是按照顺序输出的。可自行测试。
换String输入试试看