目录
一、基础元素Node
static class Node<K,V> implements Map.Entry<K,V> {
//key的hash值
final int hash;
final K key;
V value;
//通过next属性将多个hash值相同的元素关联起来,形成单向链表
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() { return key; }
public final V getValue() { return value; }
public final String toString() { return key + "=" + value; }
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
实现很简单,关键是next属性,插入、查找、删除用法如下:
@Test
public void test8() throws Exception {
Node<String,Integer> first=new Node<>(1, "1", 1, null);
Node<String,Integer> node2=new Node<>(1, "2", 1, null);
Node<String,Integer> node3=new Node<>(1, "3", 1, null);
Node<String,Integer> node4=new Node<>(1, "4", 1, null);
Node<String,Integer> node5=new Node<>(1, "5", 1, null);
//插入时建立链式关系
first.next=node2;
node2.next=node3;
node3.next=node4;
node4.next=node5;
//从头元素开始遍历查找
Node<String,Integer> n=first;
do{
if(n.key.equals("5")){
System.out.println("====元素查找======");
System.out.println(n);
}
}while ((n=n.next)!=null);
//移除元素node2
first.next=node3;
node2.next=null;
System.out.println("====移除元素======");
n=first;
do{
System.out.println(n);
}while ((n=n.next)!=null);
}
二、红黑树元素TreeNode
1、类定义和类属性
TreeNode继承自LinkedHashMap.Entry<K,V>,后者继承自HashMap.Node<K,V>,只是增加了两个属性before和after,用于保存当前节点的前后节点引用,从而形成一条可以双向遍历的链表。TreeNode继承自LinkedHashMap.Entry<K,V>是为了方便LinkedHashMap实现,本身并没有直接使用before和after两个属性。LinkedHashMap.Entry<K,V>的定义如下图:
TreeNode定义的属性如下图:
注意TreeNode的实现同时维护了红黑树和双向链式两种应用关系,这样便于在红黑树和链表之间做形态转换。
2、基础方法:
/**
* 返回当前节点的根节点
*/
final TreeNode<K,V> root() {
for (TreeNode<K,V> r = this, p;;) {
//该节点的父节点为null时该节点为根节点
if ((p = r.parent) == null)
return r;
r = p;
}
}
/**
* 递归检查当前节点是否符合双向链表以及红黑树规则
* 该方法在红黑树发生改变时都会执行一次,确保改变后红黑树符合规范
*/
static <K,V> boolean checkInvariants(TreeNode<K,V> t) {
TreeNode<K,V> tp = t.parent, tl = t.left, tr = t.right,
tb = t.prev, tn = (TreeNode<K,V>)t.next;
//是否符合双向链表规则
if (tb != null && tb.next != t)
return false;
if (tn != null && tn.prev != t)
return false;
//是否符合红黑树规则
if (tp != null && t != tp.left && t != tp.right)
return false;
//左节点的hash值必须小于根节点hash值
if (tl != null && (tl.parent != t || tl.hash > t.hash))
return false;
//右节点hash值大于根节点hash值
if (tr != null && (tr.parent != t || tr.hash < t.hash))
return false;
//红色节点的子节点一定不能是红色
if (t.red && tl != null && tl.red && tr != null && tr.red)
return false;
//递归检查左节点和右节点
if (tl != null && !checkInvariants(tl))
return false;
if (tr != null && !checkInvariants(tr))
return false;
return true;
}
/**