我知道无法保证hashmap中键的顺序。如果没有重新哈希或哈希冲突,会重新排序吗?
我们真的不应该担心!
在检查HashMap的源代码时,它内部似乎使用了HashMap.Entry对象的数组,用于查找所需条目的数组索引基于对象的hashCode()和数组的大小。因此,排序与对象的hashCode和Map的大小有关。
然而,这只是一种简化,我只研究了OpenJDK 6中的实现。
您永远不应该依赖于实现细节。之所以有一个名为Map的接口,有一个很好的理由:它定义了应该如何使用它。
特别是在java.util.HashMap
中,只有在达到最大阈值时,条目才会被移动和重新排序。方法addEntry()
调用resize()
方法,该方法将密钥转移到新的表中重新排列
768 void addEntry(int hash, K key, V value, int bucketIndex) {
//
771 if (size++ >= threshold)
772 resize(2 * table.length);
471 void resize(int newCapacity) {
//
479 Entry[] newTable = new Entry[newCapacity];
480 transfer(newTable);
481 table = newTable;
看看这个有趣的链接,它详细展示了Hashmap的工作原理:以下是如何投入和获得工作解释:
具有相同哈希值的所有密钥都被放在相同的链表(bucket)中。具有不同哈希值的密钥最终可能会在同一个存储桶中。
当用户调用put(K键,V值)或get(Object键)时,函数会计算Entry应该所在的bucket的索引。然后,函数会遍历列表,查找具有相同键的Entry(使用键的equals()函数)。
在get()的情况下,函数返回与该条目相关联的值(如果该条目存在)。
在put(K键,V值)的情况下,如果条目存在,函数会用新值替换它,否则它会在单链表的开头创建一个新条目(根据参数中的键和值)。