本帖最后由 张洪慊 于 2014-1-2 16:45 编辑
首先你要了解存入的key所属类的hashCode方法:
Integer中hashCode()已被复写:
- public int hashCode() {
- return value;//这个value就是你的Integer对象对应的int值
- }
复制代码
接着向HashMap添加元素用到三个方法:
- //put
- public V put(K key, V value) {
- if (table == EMPTY_TABLE) {
- inflateTable(threshold);
- }
- if (key == null)
- return putForNullKey(value);
- int hash = hash(key);//这个会按照哈希算法求出key的哈希值
- int i = indexFor(hash, table.length);//hash&table.length-1算出在哈希表中的index
- for (Entry<K,V> e = table; 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;
- }
复制代码- final int hash(Object k) {
- int h = hashSeed;
- if (0 != h && k instanceof String) {
- return sun.misc.Hashing.stringHash32((String) k);
- }
- h ^= k.hashCode();//将调用Integer的hashCode:例如添加key=5,返回5
- // This function ensures that hashCodes that differ only by
- // constant multiples at each bit position have a bounded
- // number of collisions (approximately 8 at default load factor).
- h ^= (h >>> 20) ^ (h >>> 12);
- return h ^ (h >>> 7) ^ (h >>> 4);
- }
复制代码 h ^= (h >>> 20) ^ (h >>> 12); h ^ (h >>> 7) ^ (h >>> 4);
算出来到底是多少?
你不妨让计算机帮我们算:
int h=5;
h ^= (h >>> 20) ^ (h >>> 12);
h ^ (h >>> 7) ^ (h >>> 4);
h的结果依然是5
那么计算出index: (初始表长16)
5&(16-1)=5
那么他将被添加到table[5]中
这么绕了一大圈,每个int值算出来的哈希值还是该int值...
加断点Debug:
但是如果添加的int值为16(表长16,最大index:15)
此时:
上图:key为16计算出的hash=17,17&(16-1)=1
那么在输出HashMap时,最先输出的元素 key=16的元素,接着输出key为4,5...这时候就不是从小到大.
究其原因就是Integer的hashCode方法直接返回其对应的int值,很大概率导致你的key与表中的索引一致,也就是你的输出结果,但不是绝对的,碰巧吧
|
|