在 Java 中,HashMap 是一个非常常用的数据结构,用于存储键值对。它提供了快速的查找、插入和删除操作。HashMap 的核心功能之一是根据键获取对应的值,这主要通过 get() 方法来实现。本文将详细介绍 HashMap 的 get() 方法及其相关的辅助方法,包括 getNode()、hash()、getTreeNode()、root()、find()、comparableClassFor() 和 compareComparables()。通过这些方法的解析,您将更深入地理解 HashMap 的内部工作原理。
下面我们先来大致看一下hashMap的get()方法获取数据的大致流程,以便在看下面的源码不至于太迷茫。
HashMap get()方法
//根据key获取Node
public V get(Object key) {
Node<K,V> e;
//计算key的哈希码,调用getNode方法,传入哈希码和键,获取对应的Node
//如果找到的Node为null,返回null;否则返回该Node的值
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
下面来看下hash()方法和getNode节点方法
getNode()的流程图比较复杂,我们拆分开来看
getNode()方法获取节点
获取节点大致分为四个步骤:
- 获取桶:根据哈希值计算桶的位置,并获取该桶的第一个节点。
- 直接匹配:检查第一个节点是否匹配,如果匹配直接返回。
- 深入查找:
- 如果是红黑树节点,使用红黑树的方法进行查找。
- 如果是链表节点,遍历链表查找匹配节点。
- 结果返回:找到匹配节点则返回该节点,否则返回 null
//传入哈希码和key
final Node<K,V> getNode(int hash, Object key) {
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
//检查table是否为空且长度大于0 && 使用(n-1)&hash计算索引桶(n是table长度),并获取该桶的第一个节点first
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) {
//检查first节点是否与给定的hash和key匹配,如果匹配,直接返回first
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
return first;
//如果不匹配,检查first的下一个节点e
if