首页>代码>java数据结构之红黑树实现hashMap源码>/hashMap/src/com/mjy/map/HashMap.java
package com.mjy.map;

import com.mjy.printer.BinaryTreeInfo;
import com.mjy.printer.BinaryTrees;

import java.util.LinkedList;
import java.util.Objects;
import java.util.Queue;

/**
 * ***************************************************
 * 
 * @ClassName HashMap
 * @Description 描述
 * @Author maojianyun
 * @Date 2020/1/10 13:53
 * @Version V1.0 ****************************************************
 **/
@SuppressWarnings({ "unchecked", "unused" })
public class HashMap<K, V> implements Map<K, V> {

	private final static boolean RED = false;
	private final static boolean BLACK = true;
	private Node<K, V>[] table;
	private int size;
	private static final int DEFAULT_CAPACITY = 1 << 4;
	private static final float DEFAULT_LOAD_FACTOR = 0.75f;
	public HashMap() {
		table = new Node[DEFAULT_CAPACITY];
	}

	public int size() {
		return size;
	}

	public boolean isEmpty() {
		return size == 0;
	}

	public void clear() {
		if (size == 0) {
			return;
		}
		size = 0;
		for (int i = 0; i < table.length; i++) {
			table[i] = null;
		}
	}

	public V put(K key, V value) {
		resize();
		int index = index(key);
		// 取出index位置的红黑树根节点
		Node<K, V> root = table[index];
		if (root == null) {
			root = new Node<K, V>(key, value, null);
			table[index] = root;
			size++;
			// 修复红黑树性质
			afterPut(root);
			return null;
		}
		// 添加新的节点到红黑树上面
		Node<K, V> parent = root;
		Node<K, V> node = root;
		int cmp = 0;
		K k1 = key;
		int h1 = k1 == null ? 0 : k1.hashCode();
		Node<K, V> result = null;
		boolean searched = false; // 是否已经搜索过这个key
		do {
			parent = node;
			K k2 = node.key;
			int h2 = node.hash;
			if (h1 > h2) {
				cmp = 1;
			} else if (h1 < h2) {
				cmp = -1;
			} else if (Objects.equals(k1, k2)) {
				cmp = 0;
			} else if (k1 != null && k2 != null 
					&& k1.getClass() == k2.getClass() 
					&& k1 instanceof Comparable
					&& (cmp = ((Comparable<K>) k1).compareTo(k2)) != 0) {

			} else if (searched) { // 已经扫描了
				cmp = System.identityHashCode(k1) - System.identityHashCode(k2);
			} else {
				if ((node.left != null && (result = node(node.left, k1)) != null)
						|| (node.right != null && (result = node(node.right, k1)) != null)) {
					// 已经存在这个key
					node = result;
					cmp = 0;
				} else { // 不存在这个key
					searched = true;
					cmp = System.identityHashCode(k1) - System.identityHashCode(k2);
				}
			}
			if (cmp > 0) {
				node = node.right;
			} else if (cmp < 0) {
				node = node.left;
			} else { // 相等
				V oldValue = node.value;
				node.key = key;
				node.value = value;
				node.hash = h1;
				return oldValue;
			}
		} while (node != null);
		Node<K, V> newNode = new Node<K, V>(key, value, parent);
		if (cmp > 0) {
			parent.right = newNode;
		} else {
			parent.left = newNode;
		}
		size++;
		afterPut(newNode);
		return null;
	}

	public V get(K key) {
		Node<K, V> node = node(key);
		return node != null ? node.value : null;
	}

	public V remove(K key) {
		return remove(node(key));
	}

	public boolean containsKey(K key) {
		return node(key) != null;
	}

	public boolean containsValue(V value) {
		if (size == 0) {
			return false;
		}
		for (int i = 0; i < table.length; i++) {
			if (table[i] == null) {
				continue;
			}
			Queue<Node<K, V>> queue = new LinkedList<>();
			queue.offer(table[i]);
			while (!queue.isEmpty()) {
				Node<K, V> node = queue.poll();
				if (Objects.equals(value, node.value)) {
					return true;
				}
				if (node.left != null) {
					queue.offer(node.left);
				}
				if (node.right != null) {
					queue.offer(node.right);
				}
			}
		}
		return false;
	}

	public void traversal(Visitor<K, V> visitor) {
		if (size == 0 || visitor.stop) {
			return;
		}
		Queue<Node<K, V>> queue = new LinkedList<>();
		for (int i = 0; i < table.length; i++) {
			if (table[i] == null) {
				continue;
			}
			queue.offer(table[i]);
			while (!queue.isEmpty()) {
				Node<K, V> node = queue.poll();
				visitor.stop = visitor.visit(node.key, node.value);
				if (node.left != null) {
					queue.offer(node.left);
				}
				if (node.right != null) {
					queue.offer(node.right);
				}
			}
		}
	}

	/**
	 * 删除node
	 *
	 * @param node
	 * @return
	 */
	private V remove(Node<K, V> node) {
		if (node == null) {
			return null;
		}
		V oldValue = node.value;
		if (node.hasTwoChildren()) { // 度为2的节点
			// 找到后继节点
			Node<K, V> su = successor(node);
			// 用后继节点的值覆盖度为2的节点的值
			node.key = su.key;
			node.value = su.value;
			node.hash = su.hash;
			// 删除后继节点
			node = su;
		}
		// 删除node节点(node的度必然是1或者0)
		// 如果度为1、则返回的是其子节点
		Node<K, V> replacement = node.left != null ? node.left : node.right;
		int index = index(node);
		if (replacement != null) { // 删除度为1的节点
			replacement.parent = node.parent;
			if (node.parent == null) {
				table[index] = replacement;
			} else if (node.isLeftChild()) {
				node.parent.left = replacement;
			}
			if (node.isRightChild()) {
				node.parent.right = replacement;
			}
			// 删除节点之后的处理
			afterRemove(replacement);
		} else if (node.parent == null) { // node是叶子节点并且是根节点
			table[index] = null;
		} else { // node是叶子节点,但不是根节点
			if (node == node.parent.left) {
				node.parent.left = null;
			} else { // node == node.parent.right
				node.parent.right = null;
			}
			// 删除节点之后的处理
			afterRemove(node);
		}
		size--;
		return oldValue;
	}
	
	private void resize() {
		// 装填因子 <= 0.75
		if (size / table.length <= DEFAULT_LOAD_FACTOR) {
			return;
		}
		Node<K, V> [] oldTable = table;
		table = new Node[oldTable.length << 1];
		Queue<Node<K, V>> queue = new LinkedList<Node<K,V>>();
		for(int i = 0; i < oldTable.length; i++) {
			if (oldTable[i] == null) {
				continue;
			}
			queue.offer(oldTable[i]);
			while(!queue.isEmpty()) {
				Node<K, V> node = queue.poll();
				if (node.left != null) {
					queue.offer(node.left);
				}
				if (node.right != null) {
					queue.offer(node.right);
				}
				// 挪动代码得放到最后面
				moveNode(node);
			}
		}
	}
	
	private void moveNode(Node<K, V> newNode) {
		// 重置
		newNode.parent = null;
		newNode.left = null;
		newNode.right = null;
		newNode.color = RED;
		
		int index = index(newNode);
		// 取出index位置的红黑树根节点
		Node<K, V> root = table[index];
		if (root == null) {
			root = newNode;
			table[index] = root;
			afterPut(root);
			return;
		}
		
		// 添加新的节点到红黑树上面
		Node<K, V> parent = root;
		Node<K, V> node = root;
		int cmp = 0;
		K k1 = newNode.key;
		int h1 = newNode.hash;
		do {
			parent = node;
			K k2 = node.key;
			int h2 = node.hash;
			if (h1 > h2) {
				cmp = 1;
			} else if (h1 < h2) {
				cmp = -1;
			} else if (k1 != null && k2 != null 
					&& k1 instanceof Comparable
					&& k1.getClass() == k2.getClass()
					&& (cmp = ((Comparable<K>)k1).compareTo(k2)) != 0) {
			} else {
				cmp = System.identityHashCode(k1) - System.identityHashCode(k2);
			}
			
			if (cmp > 0) {
				node = node.right;
			} else if (cmp < 0) {
				node = node.left;
			}
		} while (node != null);

		// 看看插入到父节点的哪个位置
		newNode.parent = parent;
		if (cmp > 0) {
			parent.right = newNode;
		} else {
			parent.left = newNode;
		}
		
		// 新添加节点之后的处理
		afterPut(newNode);
	}

	/**
	 * 得到节点的后继节点
	 *
	 * @param node
	 * @return
	 */
	private Node<K, V> successor(Node<K, V> node) {
		if (node == null)
			return null;

		// 前驱节点在左子树当中(right.left.left.left....)
		Node<K, V> p = node.right;
		if (p != null) {
			while (p.left != null) {
				p = p.left;
			}
			return p;
		}

		// 从父节点、祖父节点中寻找前驱节点
		while (node.parent != null && node == node.parent.right) {
			node = node.parent;
		}
		return node.parent;
	}

	private Node<K, V> node(K key) {
		Node<K, V> root = table[index(key)];
		return root == null ? null : node(root, key);
	}

	private Node<K, V> node(Node<K, V> node, K k1) {
		int h1 = k1 == null ? 0 : k1.hashCode();
		// 存储查找结果
		Node<K, V> result = null;
		int cmp = 0;
		while (node != null) {
			K k2 = node.key;
			int h2 = node.hash;
			// 先比较哈希值
			if (h1 > h2) {
				node = node.right;
			} else if (h1 < h2) {
				node = node.left;
			} else if (Objects.equals(k1, k2)) {
				return node;
			} else if (k1 != null && k2 != null 
				&& k1.getClass() == k2.getClass()
				&& k1 instanceof Comparable
				&& (cmp = ((Comparable<K>) k1).compareTo(k2)) != 0) {
				node = cmp > 0 ? node.right : node.left;
			} else if (node.right != null && (result = node(node.right, k1)) != null) { 
				return result;
			} else { // 只能往左边找
				node = node.left;
			}
		}
		return null;
	}

	/**
	 * 得到hash索引(在数组中的索引下标)
	 *
	 * @param key
	 * @return
	 */
	private int index(K key) {
		if (key == null) {
			return 0;
		}
		int hash = key.hashCode();
		hash = hash ^ (hash >>> 16);
		return hash & (table.length - 1);
	}

	private int index(Node<K, V> node) {
		if (node == null) {
			return 0;
		}
		int hash = node.hash;
		hash = hash ^ (hash >>> 16);
		return hash & (table.length - 1);
	}

	private void afterPut(Node<K, V> node) {
		Node<K, V> parent = node.parent;
		// 添加的是根节点 或者 上溢到达了根节点
		if (parent == null) {
			black(node);
			return;
		}
		// 如果父节点是黑色,直接返回
		if (isBlack(parent)) {
			return;
		}
		// 叔父节点
		Node<K, V> uncle = parent.sibling();
		// 祖父节点
		Node<K, V> grand = red(parent.parent);
		if (isRed(uncle)) { // 叔父节点是红色【B树节点上溢】
			black(parent);
			black(uncle);
			// 把祖父节点当做是新添加的节点
			afterPut(grand);
			return;
		}
		// 叔父节点不是红色
		if (parent.isLeftChild()) { // L
			if (node.isLeftChild()) { // LL
				black(parent);
			} else { // LR
				black(node);
				rotateLeft(parent);
			}
			rotateRight(grand);
		} else { // R
			if (node.isLeftChild()) { // RL
				black(node);
				rotateRight(parent);
			} else { // RR
				black(parent);
			}
			rotateLeft(grand);
		}
	}

	private void afterRemove(Node<K, V> node) {
		// 如果删除的节点是红色
		// 或者 用以取代删除节点的子节点是红色
		if (isRed(node)) {
			black(node);
			return;
		}
		Node<K, V> parent = node.parent;
		if (parent == null) {
			return;
		}
		// 删除的是黑色叶子节点【下溢】
		// 判断被删除的node是左还是右
		boolean left = parent.left == null || node.isLeftChild();
		Node<K, V> sibling = left ? parent.right : parent.left;
		if (left) { // 被删除的节点在左边,兄弟节点在右边
			if (isRed(sibling)) { // 兄弟节点是红色
				black(sibling);
				red(parent);
				rotateLeft(parent);
				// 更换兄弟
				sibling = parent.right;
			}

			// 兄弟节点必然是黑色
			if (isBlack(sibling.left) && isBlack(sibling.right)) {
				// 兄弟节点没有1个红色子节点,父节点要向下跟兄弟节点合并
				boolean parentBlack = isBlack(parent);
				black(parent);
				red(sibling);
				if (parentBlack) {
					afterRemove(parent);
				}
			} else { // 兄弟节点至少有1个红色子节点,向兄弟节点借元素
				// 兄弟节点的左边是黑色,兄弟要先旋转
				if (isBlack(sibling.right)) {
					rotateRight(sibling);
					sibling = parent.right;
				}

				color(sibling, colorOf(parent));
				black(sibling.right);
				black(parent);
				rotateLeft(parent);
			}
		} else { // 被删除的节点在右边,兄弟节点在左边
			if (isRed(sibling)) { // 兄弟节点是红色
				black(sibling);
				red(parent);
				rotateRight(parent);
				// 更换兄弟
				sibling = parent.left;
			}

			// 兄弟节点必然是黑色
			if (isBlack(sibling.left) && isBlack(sibling.right)) {
				// 兄弟节点没有1个红色子节点,父节点要向下跟兄弟节点合并
				boolean parentBlack = isBlack(parent);
				black(parent);
				red(sibling);
				if (parentBlack) {
					afterRemove(parent);
				}
			} else { // 兄弟节点至少有1个红色子节点,向兄弟节点借元素
				// 兄弟节点的左边是黑色,兄弟要先旋转
				if (isBlack(sibling.left)) {
					rotateLeft(sibling);
					sibling = parent.left;
				}

				color(sibling, colorOf(parent));
				black(sibling.left);
				black(parent);
				rotateRight(parent);
			}
		}
	}

	/**
	 * 给指定节点染指定的颜色
	 *
	 * @param node  节点
	 * @param color 颜色
	 * @return 节点
	 */
	private Node<K, V> color(Node<K, V> node, boolean color) {
		if (node != null) {
			node.color = color;
		}
		return node;
	}

	/**
	 * 节点染成红色
	 *
	 * @param node
	 * @return
	 */
	private Node<K, V> red(Node<K, V> node) {
		return color(node, RED);
	}

	/**
	 * 节点染成黑色
	 *
	 * @param node
	 * @return
	 */
	private Node<K, V> black(Node<K, V> node) {
		return color(node, BLACK);
	}

	/**
	 * 得到节点的颜色
	 *
	 * @param node
	 * @return
	 */
	private boolean colorOf(Node<K, V> node) {
		return node == null ? BLACK : node.color;
	}

	/**
	 * 是否是黑色
	 *
	 * @param node
	 * @return
	 */
	private boolean isBlack(Node<K, V> node) {
		return colorOf(node) == BLACK;
	}

	/**
	 * 是否是红色
	 *
	 * @param node
	 * @return
	 */
	private boolean isRed(Node<K, V> node) {
		return colorOf(node) == RED;
	}

	private void rotateLeft(Node<K, V> grand) {
		Node<K, V> parent = grand.right;
		Node<K, V> child = parent.left;
		grand.right = child;
		parent.left = grand;
		afterRotate(grand, parent, child);
	}

	private void rotateRight(Node<K, V> grand) {
		Node<K, V> parent = grand.left;
		Node<K, V> child = parent.right;
		grand.left = child;
		parent.right = grand;
		afterRotate(grand, parent, child);
	}

	private void afterRotate(Node<K, V> grand, Node<K, V> parent, Node<K, V> child) {
		// 让parent称为子树的根节点
		parent.parent = grand.parent;
		if (grand.isLeftChild()) {
			grand.parent.left = parent;
		} else if (grand.isRightChild()) {
			grand.parent.right = parent;
		} else { // grand是root节点
			table[index(grand.key)] = parent;
		}

		// 更新child的parent
		if (child != null) {
			child.parent = grand;
		}

		// 更新grand的parent
		grand.parent = parent;
	}

	/**
	 * ***************************************************
	 *
	 * @ClassName Node<K , V>
	 * @Description 红黑树节点
	 * @Author maojianyun
	 * @Date 2020/1/9 22:06
	 * @Version V1.0 ****************************************************
	 **/
	private static class Node<K, V> {
		// 默认为红色
		boolean color = RED;
		int hash;
		K key;
		V value;
		Node<K, V> left;
		Node<K, V> right;
		Node<K, V> parent;

		public Node(K key, V value, Node<K, V> parent) {
			this.key = key;
			this.hash = key == null ? 0 : key.hashCode();
			this.value = value;
			this.parent = parent;
		}

		/**
		 * 是否是叶子节点
		 *
		 * @return
		 */
		public boolean isLeaf() {
			return left == null && right == null;
		}

		/**
		 * 是否有两个孩子
		 *
		 * @return
		 */
		public boolean hasTwoChildren() {
			return left != null && right != null;
		}

		/**
		 * 是否是左孩子
		 *
		 * @return
		 */
		public boolean isLeftChild() {
			return parent != null && this == parent.left;
		}

		/**
		 * 是否是右孩子
		 *
		 * @return
		 */
		public boolean isRightChild() {
			return parent != null && this == parent.right;
		}

		/**
		 * 得到兄弟节点
		 *
		 * @return
		 */
		public Node<K, V> sibling() {
			if (isLeftChild()) {
				return parent.right;
			}
			if (isRightChild()) {
				return parent.left;
			}
			return null;
		}

		@Override
		public String toString() {
			return color + "_Node_" + key + "_" + value;
		}
	}

	public void print() {
		if (size == 0)
			return;
		for (int i = 0; i < table.length; i++) {
			final Node<K, V> root = table[i];
			System.out.println("【index = " + i + "】");
			BinaryTrees.println(new BinaryTreeInfo() {
				@Override
				public Object string(Object node) {
					return node;
				}

				@Override
				public Object root() {
					return root;
				}

				@Override
				public Object right(Object node) {
					return ((Node<K, V>) node).right;
				}

				@Override
				public Object left(Object node) {
					return ((Node<K, V>) node).left;
				}
			});
			System.out.println("---------------------------------------------------");
		}
	}
}
最近下载更多
matintalorr  LV10 2021年8月31日
17600446733  LV21 2020年6月23日
2650343087  LV6 2020年5月26日
wyyxhzzp  LV1 2020年2月18日
宇1314520乔  LV1 2020年1月31日
dajian  LV1 2020年1月18日
最代码官方  LV168 2020年1月16日
最近浏览更多
3334004690  LV10 3月6日
如果不曾相遇  LV3 2023年5月6日
我爱你野狼123 2023年3月22日
暂无贡献等级
woaini12788  LV7 2022年1月17日
ooooops 2022年1月11日
暂无贡献等级
luozf1990  LV3 2022年1月4日
matintalorr  LV10 2021年8月31日
絮落无痕  LV13 2021年4月21日
孤独の王者  LV6 2021年4月17日
蹦迪的小熊  LV5 2021年4月8日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友