JAVA基础知识-HashMap 相关知识。
常用的通配符
T, E, K, V, ?
本质上没有任何区别,但是为了维持可读性,常这样约定:
?表示不确定的JAVA类型
T (type) 表示一个具体的JAVA类型
K V (key value) 分别表示JAVA键值对 key - value
E (element) 代表Element
RBT(红黑树)
- 每个节点是红色或者黑色
- 根节点是黑色
- 每个叶节点是黑色的
- 如果一个节点是红色的,则它的两个儿子都是黑色的
- 对于每个节点,从该结点到其叶子节点构成的所有路径上的黑色结点个数相同
插入过程:
默认插入节点为红色
AVL(自平衡二叉查找树)
首先是一棵二叉查找树
某节点的左子树节点值仅包含小于该节点值
某节点的右子树节点值仅包含大于该节点值
左右子树每个也必须是二叉查找树
带有平衡条件,每个结点的左右子树的高度之差的绝对值(平衡因子)最多为1
RBT和AVL
查找远远多于插入删除,选择AVL树
如果查找、插入、删除频率差不多,那么选择红黑树
JAVA 中红黑树的实现
1 | static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> { |
红黑树的插入过程:
1 | static <K,V> TreeNode<K,V> balanceInsertion(TreeNode<K,V> root, TreeNode<K,V> x) { |
左旋右旋方法:
1 | static <K,V> TreeNode<K,V> rotateLeft(TreeNode<K,V> root, TreeNode<K,V> p) { |
红黑树的删除过程:
- 先进行二叉搜索树的删除
- 然后进行红黑树的调整
1 | // p是待删除节点,replacement用于后续的红黑树调整,指向的是p或者p的继承者。 |
删除后的调整
1 | // root : 根节点 | x : 根节点的继承者 |
重写HashCode()方法和Equals()方法
1 | // Prediction.java |
1 | // Groundhog.java |
1 | // SpringDetector.java |
Output:
1 | MAP{Groundhog #1=Six more weeks of Winner!, Groundhog #4=Six more weeks of Winner!, Groundhog #5=Early Spring, Groundhog #3=Early Spring, Groundhog #8=Six more weeks of Winner!, Groundhog #7=Early Spring, Groundhog #0=Six more weeks of Winner!, Groundhog #2=Early Spring, Groundhog #9=Six more weeks of Winner!, Groundhog #6=Early Spring} |
Groundhog默认调用的是基类Object的hashCode方法,默认使用的是对象的地址计算的散列码。同时只重写hashCode()方法是不够的,还需要重写equals()方法。
补充一句,hashCode()是基类Object的方法,所有Java对象都能产生散列码。
1 | // Groundhog2.java |
1 | // SpringDetector2.java |
Output:
1 | MAP{Groundhog #0=Six more weeks of Winner!, Groundhog #1=Six more weeks of Winner!, Groundhog #2=Early Spring, Groundhog #3=Early Spring, Groundhog #4=Six more weeks of Winner!, Groundhog #5=Early Spring, Groundhog #6=Early Spring, Groundhog #7=Early Spring, Groundhog #8=Six more weeks of Winner!, Groundhog #9=Six more weeks of Winner!} |