HashSet真的是无序的吗?
来源:互联网 发布:写曲谱的软件 编辑:程序博客网 时间:2024/03/28 20:25
首先声明:我用的是JDK1.6,因为才学Java不久,所以写的是很肤浅的东西,高手可以直接略过或鄙视,希望能给那些像我一样的新手带来帮助!
好了,喝口水滋润一下嗓子,争取一口气说完。
HashSet底层维护的实际上是一个Entry类型的数组(数组名为table),而我们知道一般数据存入数组的时候,我们是按先后顺序一个一个存入的,如:先存table[0],再存table[1]……但HashSet的源代码则不是这样存储的,我这里向HashSet中加入的元素是字符串,加入其他类型的元素道理也一样,OK,废话不多说,我们追踪add方法发现它是通过调用HashMap中的put方法实现的,底层代码如下:
public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key,value, i); return null; }
我们具体看addEntry(hash, key, value, i);这一句,这行代码即是把元素key加入到set中,也就是加入到table数组中,跟进去我们发现table的index并不是按照从0开始顺序向后加的,而是由这个方法的第四个参数i来决定的,我们再回去看看i是如何确定的:
int hash = hash(key.hashCode());int i = indexFor(hash, table.length);
我们发现i是由要加入的元素的hash code值和table数组的长度决定的,找到这两值我们便可以找到真正的答案了。
咳咳……提提神,我们继续走!
我们先找table的长度,因为HashSet中调用了HashMap中的方法put,所以一定先要生成HashMap的对象才能调用,于是我们在HashSet源代码中发现了下面的代码:
public HashSet() { map = new HashMap<>(); }
也就是说我们是调用HashMap不带参数的构造方法来生成对象的,于是到HashMap中我们发现:
public HashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); table = new Entry[DEFAULT_INITIAL_CAPACITY]; init(); }
这里的DEFAULT_INITIAL_CAPACITY即是我们要找的答案,它是HashMap中定义的常量,值为16,所以table数组的长度为16。
下面继续找要加入的元素的hash code值,因为这里我们加入的元素是String类型,所以我们到String中去找答案,当然不同类型的元素找到的结果不一样,但道理相通。在String中hashCode这个方法的算法是:
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
其中的s[i]表示字符串中的第i个字符,n表示字符串的长度,通过这个表达式我们便可以计算出对应的字符串的hash code。
到此我们要找的两个值都找到了,我们发现当我们向HashSet中添加元素时,HashSet底层维护的table数组添加的顺序是由加入的字符串中的具体字符以及字符串的长度决定的,并不是由添加的顺序决定的,而我们添加字符串时则不会事先去算一下这两个值的大小,也没必要,所以对Coder来说HashSet中元素的顺序是未知的,但这并不表示它本身没有顺序,因为一旦HashSet中的元素都确定了,元素的顺序便随上面的两值一起确定了,不管我们怎么运行都不会变,除非我们在运行过程中改变、添加或删除某个值。
我要说的就这么点,只要稍微看下代码就一目了然了,之所以把它写出来,是因为在学习的时候有这个疑惑,希望可以鼓励大家和我自己多看底层代码,不要只会调用而不理解原理。
最后欢迎大家拍砖和交流!
- HashSet真的是无序的吗?
- HashSet实现是无序的测试
- HashMap是无序的
- HashMap是无序的
- Set是唯一 无序的
- 咿呀,字典是无序的
- 是真的吗?
- 是真的吗?
- 是真的吗
- 真的是她吗?
- 这次是 真的吗?
- 真的是NoClassDefFoundError吗
- 预言是真的吗?
- 2012是真的吗?
- 真的是这样吗?
- JS对象属性是无序的
- python 字典为什么是无序的?
- HashMap源码分析,为什么是无序的?
- 树状数组简单题(HDU1166)
- java好的编码习惯
- mysql 复合索引 总结
- Jbox2D入门学习一物理世界及最简单的物体创建
- task_struct解析(一) 进程状态
- HashSet真的是无序的吗?
- Linux源码阅读推荐阅读图书
- css hack(ie6-9,firefox,chrome,opera,safari)
- autoFight
- NYOJ 291 LK的数学题 和 NYOJ 333 mdd的烦恼【欧拉函数】
- 计算机必读经典教材图书推荐
- 计算机码制和浮点数的学习思考
- struts数据类型转化(Double.parseDouble())(values[0].split)(string centerValues[])(properties)
- Virtual Memory Management in VAX/VMS Operating System