今天在看java8 HashMap实现原码时,发现在java8中hashmap中的元素不单单是存链表了,而是变成了链表和红黑树结合使用了,具体是:当同一hash位置的元素少于8个时,使用链表存储且采用尾插入方式,当大于等于8个时,将其转换为红黑树存储。话不多说,上原码:
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
HashMap.Node<K, V>[] tab;
HashMap.Node<K, V> p;
int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
//通过哈希值找到对应的位置,如果该位置还没有元素存在,直接插入
tab[i] = newNode(hash, key, value, null);
else {
HashMap.Node<K, V> e;
K k;
if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof HashMap.TreeNode)
//如果当前节点为树节点,则将元素插入红黑树中
e = ((HashMap.TreeNode<K, V>) p).putTreeVal(this, tab, hash, key, value);
else {
//遍历链表
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
//插入元素到链尾
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1)
//元素个数大于等于 8,改造为红黑树
treeifyBin(tab, hash);
break;
}
if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) {
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
//检查是否超出 threshold 限制,是则进行扩容
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
当看到红黑树几个字时,对其概念脑袋一片空白,只记得当时还在学校时拿c语言苦逼实现过,于是网上快速复习了一下红黑树概念,然后为了加深一下印象,便拿java写了一个红黑树,具体红黑树的介绍网上有很多,这里就不介绍了,直接上代码:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class RedBlackTree {
private RedBlackNode root;
public void print() {
Map<Integer,List<RedBlackNode>> nodeList = new LinkedHashMap<Integer,List<RedBlackNode>>();
getNode(root,1,nodeList);
Iterator<Map.Entry<Integer, List<RedBlackNode>>> iterator = nodeList.entrySet().iterator();
while(iterator.hasNext()) {
Map.Entry<Integer, List<RedBlackNode>> entry = iterator.next();
List<RedBlackNode> list = entry.getValue();
list.forEach(item->{
RedBlackNode left = item.getLeftNode();
RedBlackNode right = item.getRightNode();
RedBlackNode parent = item.getParentNode();
System.out.print("node:"+item.getValue()+" color:"+(item.getColor()?"R":"B")+" parent:"+(parent==null?"":parent.getValue())+" left:"+(left==null?"":left.getValue())+" right:"+(right==null?"":right.getValue()));
System.out.print(" ");
});
System.out.println();
}
}
private void getNode(RedBlackNode node,int deep,Map<Integer,List<RedBlackNode>> treeList) {
if(node==null) {
return;
}
List<RedBlackNode> nodeList = treeList.get(deep);
if(nodeList==null) {
nodeList = new ArrayList<RedBlackNode>();
treeList.put(deep,nodeList);
}
nodeList.add(node);
getNode(node.getLeftNode(),deep+1,treeList);
getNode(node.getRightNode(),deep+1,treeList);
}
public void insert(int value) {
RedBlackNode node = new RedBlackNode();
node.setValue(value);
insert(node);
// print();
// System.out.println("*******************************************************************************************************");
}
public void insert(RedBlackNode node) {
RedBlackNode position = getPosition(root,node);
if(position==null) {
root = node;
root.setColor(false);
return;
}
if(position.getValue()==node.getValue()) {
//进行更新操作
}else if(node.getValue() < position.getValue()){
RedBlackNode brotherNode = position.getRightNode();
position.setLeftNode(node);
node.setParentNode(position);
if(brotherNode!=null) {
node.setBrotherNode(position.getRightNode());
brotherNode.setBrotherNode(node);
}
node.setLeftRightFlag(true);
if(position.getColor()) {//父节点为红色,要变色
changeColor(node);
return;
}
}else {
RedBlackNode brotherNode = position.getLeftNode();
position.setRightNode(node);
node.setParentNode(position);
if(brotherNode!=null) {
node.setBrotherNode(brotherNode);
brotherNode.setBrotherNode(node);
}
node.setLeftRightFlag(false);
if(position.getColor()) {//父节点为红色,要变色
changeColor(node);
return;
}
}
}
public void delete(RedBlackNode node) {
}
public RedBlackNode query(RedBlackNode value) {
RedBlackNode position = getPosition(root,value);
if(position.getValue() == value.getValue()) {
return position;
}
return null;
}
private void changeColor(RedBlackNode node) {
RedBlackNode parentNode = node.getParentNode();
if(parentNode==null || !parentNode.getColor()) {//根节点
return ;
}else {
RedBlackNode uncleNode = parentNode.getBrotherNode();
if(parentNode.isLeftRightFlag()) {//当父节点是祖父节点的左子时
if(uncleNode==null || uncleNode.getColor()==false) {//节点为null时默认是黑色
if(node.isLeftRightFlag()) {//当前node是父节点的左子,则当前节点的父节点变为黑色,祖父节点变为红色,对祖父节点进行旋转操作
parentNode.setColor(false);
RedBlackNode grandpaNode = parentNode.getParentNode();
if(grandpaNode!=null) {
grandpaNode.setColor(true);
this.rightSpin(grandpaNode);
changeColor(grandpaNode);
}
}else {//当前节点是父节点的右子,直接针对当前节点的父节点进行左旋操作
this.leftSpin(parentNode);
changeColor(parentNode);
}
}else {//叔叔节点为红色时,将父节点和叔叔节点变为黑色,祖父节点变为红色,然后将祖父节点作为当前节点进一步进行变色处理
uncleNode.setColor(false);
parentNode.setColor(false);
RedBlackNode grandpaNode = parentNode.getParentNode();
grandpaNode.setColor(true);
changeColor(grandpaNode);
}
}else {
if(uncleNode==null || uncleNode.getColor()==false) {//节点为null时默认是黑色
if(node.isLeftRightFlag()) {//当前node是父节点的左子,则当前节点的父节点变为黑色,祖父节点变为红色,对祖父节点进行旋转操作
this.rightSpin(parentNode);
changeColor(parentNode);
}else {//当前节点是父节点的右子,直接针对当前节点的父节点进行左旋操作
parentNode.setColor(false);
RedBlackNode grandpaNode = parentNode.getParentNode();
if(grandpaNode!=null) {
grandpaNode.setColor(true);
this.leftSpin(grandpaNode);
changeColor(grandpaNode);
}
}
}else {//叔叔节点为红色时,将父节点和叔叔节点变为黑色,祖父节点变为红色,然后将祖父节点作为当前节点进一步进行变色处理
uncleNode.setColor(false);
parentNode.setColor(false);
RedBlackNode grandpaNode = parentNode.getParentNode();
if(root!=grandpaNode) {
grandpaNode.setColor(true);
changeColor(grandpaNode);
}
}
}
}
}
/**
* 针对节点进行左旋操作
* @param node
*/
private void leftSpin(RedBlackNode node) {
RedBlackNode parentNode= node.getParentNode();
RedBlackNode brotherBode = node.getBrotherNode();
boolean leftRightFlag = node.isLeftRightFlag();
RedBlackNode leftChild = node.getLeftNode();
RedBlackNode rightChild = node.getRightNode();
RedBlackNode leftGrandSon = rightChild==null?null:rightChild.getLeftNode();
RedBlackNode rightGrandSon = rightChild==null?null:rightChild.getRightNode();
node.setParentNode(rightChild);
node.setBrotherNode(rightGrandSon);
node.setLeftRightFlag(true);
node.setRightNode(leftGrandSon);
if(leftChild!=null) {
leftChild.setBrotherNode(leftGrandSon);
}
if(rightChild!=null) {
rightChild.setLeftNode(node);
rightChild.setParentNode(parentNode);
rightChild.setBrotherNode(brotherBode);
rightChild.setLeftRightFlag(leftRightFlag);
}
if(leftGrandSon!=null) {
leftGrandSon.setParentNode(node);
leftGrandSon.setBrotherNode(leftChild);
leftGrandSon.setLeftRightFlag(false);
}
if(rightGrandSon!=null) {
rightGrandSon.setBrotherNode(node);
}
if(brotherBode!=null) {
brotherBode.setBrotherNode(rightChild);
}
if(parentNode!=null) {
if(leftRightFlag) {
parentNode.setLeftNode(rightChild);
}else {
parentNode.setRightNode(rightChild);
}
}else {
root = rightChild;
}
}
/**
* 针对节点进行右旋操作
* @param node
*/
private void rightSpin(RedBlackNode node) {
RedBlackNode parentNode= node.getParentNode();
RedBlackNode brotherBode = node.getBrotherNode();
boolean leftRightFlag = node.isLeftRightFlag();
RedBlackNode leftChild = node.getLeftNode();
RedBlackNode rightChild = node.getRightNode();
RedBlackNode rightGrandSon = leftChild==null?null:leftChild.getRightNode();
RedBlackNode leftGrandSon = leftChild==null?null:leftChild.getLeftNode();
node.setParentNode(leftChild);
node.setBrotherNode(leftGrandSon);
node.setLeftRightFlag(false);
node.setLeftNode(rightGrandSon);
if(leftChild!=null) {
leftChild.setParentNode(parentNode);
leftChild.setBrotherNode(brotherBode);
leftChild.setLeftRightFlag(leftRightFlag);
leftChild.setRightNode(node);
}
if(rightChild!=null) {
rightChild.setBrotherNode(rightGrandSon);
}
if(rightGrandSon!=null) {
rightGrandSon.setParentNode(node);
rightGrandSon.setBrotherNode(rightChild);
rightGrandSon.setLeftRightFlag(true);
}
if(leftGrandSon!=null) {
leftGrandSon.setBrotherNode(node);
}
if(brotherBode!=null) {
brotherBode.setBrotherNode(leftChild);
}
if(parentNode!=null) {
if(leftRightFlag) {
parentNode.setLeftNode(leftChild);
}else {
parentNode.setRightNode(leftChild);
}
}else {
root = leftChild;
}
}
private RedBlackNode getPosition(RedBlackNode root,RedBlackNode value) {
if(root==null) {
return null;
}
if(root.getValue()==value.getValue()) {
return root;
}else if(value.getValue()<root.getValue()) {
if(root.getLeftNode()!=null) {
return getPosition(root.getLeftNode(),value);
}else {
return root;
}
}else{
if(root.getRightNode()!=null) {
return getPosition(root.getRightNode(),value);
}else {
return root;
}
}
}
public RedBlackNode getRoot() {
return root;
}
public void setRoot(RedBlackNode root) {
this.root = root;
}
public class RedBlackNode{
private int value;
private boolean color=true;//true表示颜色为红色,false表示颜色为黑色 ,新节点默认为红色
private boolean leftRightFlag=true;//true表示当前节点为左子,false表示当前节点为右子
private RedBlackNode brotherNode;
private RedBlackNode parentNode;
private RedBlackNode leftNode;
private RedBlackNode rightNode;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public boolean getColor() {
return color;
}
public void setColor(boolean color) {
this.color = color;
}
public RedBlackNode getLeftNode() {
return leftNode;
}
public void setLeftNode(RedBlackNode leftNode) {
this.leftNode = leftNode;
}
public RedBlackNode getRightNode() {
return rightNode;
}
public void setRightNode(RedBlackNode rightNode) {
this.rightNode = rightNode;
}
public RedBlackNode getBrotherNode() {
return brotherNode;
}
public void setBrotherNode(RedBlackNode brotherNode) {
this.brotherNode = brotherNode;
}
public RedBlackNode getParentNode() {
return parentNode;
}
public void setParentNode(RedBlackNode parentNode) {
this.parentNode = parentNode;
}
public boolean isLeftRightFlag() {
return leftRightFlag;
}
public void setLeftRightFlag(boolean leftRightFlag) {
this.leftRightFlag = leftRightFlag;
}
}
public static void main(String [] args) {
int [] vals = {10,8,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18};
RedBlackTree tree = new RedBlackTree();
for(int i=0;i<vals.length;i++) {
tree.insert(vals[i]);
}
tree.print();
}
}
因为主要是为了加深印象,所以只实现了insert 、query等操作,delete操作有兴趣的可自行实现。