Java集合深入学习 - HashMap源码解析-1基础(基于jdk1.8)
Java集合深入学习 - HashMap源码解析-2查找数据(基于jdk1.8)
Java集合深入学习 - HashMap源码解析-3添加与扩容(基于jdk1.8)
Java集合深入学习 - HashMap源码解析-4删改与遍历(基于jdk1.8)
1.查找数据get
/**
* 根据key获取数据
*/
public V get(Object key) {
Node<K,V> e;
//获取节点,若节点非空,获取其value值否则返回null
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
/**
* 获取节点信息
* key 键值对的键
* hash 键的hash值
*/
final Node<K,V> getNode(int hash, Object key) {
//定义局部变量
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
//是否已有数据(table非空,table中对应hash计算后的位置有数据)
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) { //(n - 1) & hash n是2的次方,n-1的低位全是1,所以: (n - 1) & hash == hash%n
if (first.hash == hash && //判断头节点hash值是否与key的hash值相等
((k = first.key) == key || (key != null && key.equals(k)))) //比较是否相等,或者equals为true
return first; //满足条件,查找得就是当前节点
if ((e = first.next) != null) { //查找下一个节点
if (first instanceof TreeNode) //判断当前节点结构是否为红黑树节点
return ((TreeNode<K,V>)first).getTreeNode(hash, key); //获取对应节点
do { //不是红黑树节点,则是单链表结构,遍历链表
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e; //遍历到符合条件的节点,返回节点
} while ((e = e.next) != null);
}
}
return null; //未获取到对应节点 返回null
}
/**
* 红黑树 查找对应节点
*/
final TreeNode<K,V> getTreeNode(int h, Object k) {
//查找根节点 调用对应的find方法查找数据
return ((parent != null) ? root() : this).find(h, k, null);
}
/**
* 获取树的根节点
*/
final TreeNode<K,V> root() {
for (TreeNode<K,V> r = this, p;;) {//向上遍历获取根节点
if ((p = r.parent) == null)
return r;
r = p;
}
}
/**
* 查找红黑树的节点 (当前节点是查找树的根节点)
* @param h 对应key的hash值
* @param k 对应key对象
* @param kc key的class
* @return 查找到的节点
*/
final TreeNode<K,V> find(int h, Object k, Class<?> kc) {
TreeNode<K,V> p = this; //获取当前节点
do {
int ph, dir; K pk;
TreeNode<K,V> pl = p.left, pr = p.right, q;
if ((ph = p.hash) > h) //当前节点hash值大于待查找节点哈市值 说明待查找节点在当前节点的左子树上
p = pl; //查找左子树
else if (ph < h) //当前节点hash值小于待查找节点哈市值 说明待查找节点在当前节点的右子树上
p = pr; //查找右子树
else if ((pk = p.key) == k || (k != null && k.equals(pk))) //hash值相等 比较key是否相等或equals
return p; //查找到数据 返回当前节点
//hash值相等 但是key不相等并且equals方法返回false 即当前节点不是待查找节点
else if (pl == null) //当前节点的左子节点为null
p = pr; //查找其右子树
else if (pr == null) //当前节点的右子节点为null
p = pl; //查找其左子树
else if ((kc != null || //kc不为null
(kc = comparableClassFor(k)) != null) && //key对象实现了Comparable接口
(dir = compareComparables(kc, k, pk)) != 0) //k.compareTo(pk)返回结果赋值给dir
p = (dir < 0) ? pl : pr; //根据compareTo方法返回结果判断查找对应左子树还是右子树
else if ((q = pr.find(h, k, kc)) != null) //按compareTo方法查找对应数据
return q; //查找到,返回查找结果
else
p = pl; //查找其左子树
} while (p != null);
return null; //未查询到结果
}
/**
* 判断传入的Object对象x是否实现了Comparable接口 返回对应类得class
*/
static Class<?> comparableClassFor(Object x) {
if (x instanceof Comparable) {
Class<?> c; Type[] ts, as; Type t; ParameterizedType p;
if ((c = x.getClass()) == String.class) // 若传入x是String直接返回String.class
return c;
/*
* getGenericInterfaces()方法返回的是该对象的运行时类型“直接实现”的接口
* 返回的一定是接口,必然是该类型自己实现的接口,继承过来的不算。
*/
if ((ts = c.getGenericInterfaces()) != null) {
for (int i = 0; i < ts.length; ++i) { //遍历直接接口
if (((t = ts[i]) instanceof ParameterizedType) && //Type是ParameterizedType
((p = (ParameterizedType)t).getRawType() == //ParameterizedType得getRawType()是Comparable.class
Comparable.class) &&
(as = p.getActualTypeArguments()) != null && //此类型实际类型参数
as.length == 1 && as[0] == c) // 长度是1 其值为传入类的class
return c;
}
}
}
return null;
}
/**
* 如果x的类型是kc,返回k.compareTo(x)的比较结果
* 如果x为空,或者类型不是kc,返回0
*/
@SuppressWarnings({"rawtypes","unchecked"}) // for cast to Comparable
static int compareComparables(Class<?> kc, Object k, Object x) {
return (x == null || x.getClass() != kc ? 0 :
((Comparable)k).compareTo(x));
}
2.查找数据getOrDefault
/**
* 根据key获取数据,若未查找到对应数据,返回defaultValue
*/
@Override
public V getOrDefault(Object key, V defaultValue) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? defaultValue : e.value;
}
本问链接,转载请标注https://blog.csdn.net/luo_mu_hpu/article/details/106193009