关于HashMap put()和get()方法如何工作的内部结构(仅基本逻辑)
当我们使用put()
方法在HashMap
类中放置一个键实例说“key”和一个Value实例说“value”时, HashMap
类在内部做了什么。 当我们说hashMap.get(key)
时,它如何检索值?
编辑 :我不想要这里的细节,基本上试图理解更大的图片以及equals()
和hashcode()
方法在put()
和get()
操作中的作用。
如果你谈论更高的画面,它就像下面一样。这里我把项目称为Map
的key
放置物品时。
- 计算密钥的
hashcode
- 如果存在具有该
hashcode
basket
,则使用键上的equals
方法搜索该篮子中的键以确定是否要添加或替换该元素。 - 如果不存在则创建新的篮子(重新散列)并将该元素添加到该篮子中。
得到:
- 获取密钥的
hashcode
- 去那个篮子
- 在键上使用
equals
迭代将从该篮子中返回该元素。
这是在IBM jdk 1.6中完成的(我相信它对所有供应商来说都是一样的)
编辑
关于equals
和hashcode
您可能有兴趣看到这篇文章。
编辑结束
/** * Maps the specified key to the specified value. * * @param key * the key * @param value * the value * @return the value of any previous mapping with the specified key or null * if there was no mapping */ @Override public V put(K key, V value) { return putImpl(key, value); } V putImpl(K key, V value) { Entry entry; if(key == null) { entry = findNullKeyEntry(); if (entry == null) { modCount++; if (++elementCount > threshold) { rehash(); } entry = createHashedEntry(null, 0, 0); } } else { int hash = key.hashCode(); int index = hash & (elementData.length - 1); entry = findNonNullKeyEntry(key, index, hash); if (entry == null) { modCount++; if (++elementCount > threshold) { rehash(); index = hash & (elementData.length - 1); } entry = createHashedEntry(key, index, hash); } if ((cache != null) && (hash >> CACHE_BIT_SIZE == 0) && (key instanceof Integer)) { cache[hash] = value; } } V result = entry.value; entry.value = value; return result; }
从java 8
开始,对于HashMap
对象有一个性能改进,其中通过使用平衡树而不是链接列表来存储映射条目,密钥中存在大量冲突。 主要思想是,一旦哈希桶中的项目数量增长超过某个阈值,该桶就会从使用链接的条目列表切换到平衡树。 在高哈希冲突的情况下,这将改善从O(n)
到O(log n).
最坏情况性能O(log n).
基本上当存储桶变得太大时(目前: TREEIFY_THRESHOLD = 8
), HashMap
动态地将其替换为树形图的临时实现。 这种方式而不是悲观的O(n)
我们得到更好的O(log n)
。
TreeNodes
Bins(元素或节点)可以像其他任何一样遍历和使用,但是当人口过多时还支持更快的查找。 但是,由于正常使用的绝大多数垃圾箱都不是人口过多,因此在表格方法的过程中可能会延迟检查树箱的存在。
Tree
容器(即其元素都是TreeNodes
)主要由hashCode排序,但在tie的情况下,如果两个元素具有相同的“ class C implements Comparable
”,则键入其compareTo()
方法为用于订购。
由于TreeNodes
的大小约为常规节点的两倍,因此我们仅在bin包含足够节点时才使用它们。 当它们变得太小(由于移除或resize)时,它们被转换回普通箱(目前: UNTREEIFY_THRESHOLD = 6
)。 在具有良好分布的用户hashCodes
用法中,很少使用树容器。
链接到java doc
集合框架增强function