1.1 接口设计不存放相同元素。
因为集合中没有索引的概念,因此必须要给定一个遍历方法才能遍历该集合。
public interface Set1.2 链表实现{ int size(); boolean isEmpty(); void clear(); boolean contains(E e); void add(E e); void remove(E e); void traversal(Visitor visitor); public static abstract class Visitor { boolean stoop; abstract boolean visit(E e); } }
public class ListSet1.3 红黑树实现implements Set { private LinkedList list = new LinkedList<>(); @Override public int size() { return list.size(); } @Override public boolean isEmpty() { return list.isEmpty(); } @Override public void clear() { list.clear(); } @Override public boolean contains(E e) { return list.contains(e); } @Override public void add(E e) { int i = list.indexOf(e); if (i != -1){ // 如果已经存在就覆盖 list.set(i,e); }else { // 不存在新添加 list.add(e); } } @Override public void remove(E e) { int i = list.indexOf(e); if (i != -1){ list.remove(e); } } @Override public void traversal(Visitor visitor) { if (visitor == null){ return; } int size = list.size(); for (int i = 0; i < size; i++) { if (visitor.visit(list.get(i))) { return; } } }
public class TreeSet1.4 性能对比implements Set { private RBTree tree = new RBTree<>(); @Override public int size() { return tree.size(); } @Override public boolean isEmpty() { return tree.isEmpty(); } @Override public void clear() { tree.clear(); } @Override public boolean contains(E e) { return tree.contains(e); } @Override public void add(E e) { // 红黑树中已经实现了,如果相同就覆盖的功能。 tree.add(e); } @Override public void remove(E e) { tree.remove(e); } @Override public void traversal(Visitor visitor) { // 使用中序遍历 // 调用二叉树的visitor tree.inorderTraversal(new BinaryTree.Visitor () { @Override public boolean visit(E e) { return visitor.visit(e); } }); } }
- 从复杂度来看,红黑树的添加和删除都优于链表。
- 从去重性能来看,红黑树的去重性能优于链表。
- 但是红黑树的节点必须要具备可比较性,不然无法加入。
2.1 接口设计k-v形式,key是唯一的。
public interface Map2.2 实现{ int size(); boolean isEmpty(); void clear(); V put(K k, V v); V get(K k); V remove(K k); boolean containsKey(K k); boolean containsValue(V v); void traversal(Visitor visitor); public static abstract class Visitor { boolean stoop; abstract boolean visit(K k, V v); } }
因为使用链表实现的效率相当差,这里使用红黑树来实现。
public class TreeMap2.3 Map 与 Set 关系implements Map { private static final boolean RED = false; private static final boolean BLACK = true; private int size; private Node root; private Comparator comparator; public TreeMap() { this(null); } public TreeMap(Comparator comparator) { this.comparator = comparator; } @Override public int size() { return size; } @Override public boolean isEmpty() { return size == 0; } @Override public void clear() { root = null; size = 0; } @Override public V put(K k, V v) { keyNotNullCheck(k); // 添加第一个节点 if (root == null) { root = new Node<>(k, v, null); size++; // 新添加节点之后的处理 afterPut(root); return null; } // 添加的不是第一个节点 // 找到父节点 Node parent = root; Node node = root; int cmp = 0; do { cmp = compare(k, node.key); parent = node; if (cmp > 0) { node = node.right; } else if (cmp < 0) { node = node.left; } else { // 相等就把k 和 v 一块覆盖掉 node.key = k; V oldValue = node.value; node.value = v; return oldValue; } } while (node != null); // 看看插入到父节点的哪个位置 Node newNode = new Node<>(k, v, parent); if (cmp > 0) { parent.right = newNode; } else { parent.left = newNode; } size++; // 新添加节点之后的处理 afterPut(newNode); return null; } @Override public V get(K k) { Node node = node(k); return node == null ? null : node.value; } @Override public V remove(K k) { return remove(node(k)); } @Override public boolean containsKey(K k) { return node(k) != null; } @Override public boolean containsValue(V v) { if (root == null){ return false; } Queue > queue = new LinkedList<>(); queue.offer(root); while (!queue.isEmpty()){ Node poll = queue.poll(); // 判断 v 是否相等 if (valEquals(poll.value,v)){ return true; } if (poll.left != null){ queue.offer(poll.left); } if (poll.right != null){ queue.offer(poll.right); } } return false; } @Override public void traversal(Visitor visitor) { if (visitor == null){ return; } traversal(root,visitor); } private void traversal(Node node, Visitor visitor){ if (node == null || visitor.stoop){ return; } traversal(node.left,visitor); if (visitor.stoop){ return; } visitor.visit(node.key,node.value); traversal(node.right,visitor); } private boolean valEquals(V v1, V v2){ return v1 == null ? v2 == null : v1.equals(v2); } private void afterPut(Node node){ Node parent = node.parent; // 添加的是根节点 或者 上溢到达了根节点 if (parent == null) { black(node); return; } // 如果父节点是黑色,直接返回 if (isBlack(parent)) { return; } // 叔父节点 Node uncle = parent.sibling(); // 祖父节点 Node 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 keyNotNullCheck(K key) { if (key == null) { throw new IllegalArgumentException("key must not be null"); } } // 红黑树颜色相关 private Node color(Node node, boolean color) { if (node == null) { return node; } node.color = color; return node; } private Node red(Node node) { return color(node, RED); } private Node black(Node node) { return color(node, BLACK); } private boolean colorOf(Node node) { return node == null ? BLACK : node.color; } private boolean isBlack(Node node) { return colorOf(node) == BLACK; } private boolean isRed(Node node) { return colorOf(node) == RED; } private int compare(K e1, K e2) { if (comparator != null) { return comparator.compare(e1, e2); } return ((Comparable )e1).compareTo(e2); } // 旋转 private void rotateLeft(Node grand){ Node parent = grand.right; Node child = parent.left; grand.right = child; parent.left = grand; afterRotate(grand, parent, child); } private void rotateRight(Node grand){ Node parent = grand.left; Node child = parent.right; grand.left = child; parent.right = grand; afterRotate(grand, parent, child); } private void afterRotate(Node grand, Node parent, Node child){ // 更新 parent // 更新 p 的 parent 使成为当前子树的根节点 parent.parent = grand.parent; if (grand.isLeftChild()){ grand.parent.left = parent; }else if (grand.isRightChild()){ grand.parent.right = parent; }else { // grand 是根节点 root = parent; } // 更新 p.left 的 parent if (child != null){ child.parent = grand; } // 更新 g 的 parent grand.parent = parent; } private Node node(K k){ Node node = this.root; while (node != null){ int cmp = compare(k,node.key); if (cmp == 0){ return node; } if (cmp > 0){ node = node.right; }else { node = node.left; } } return null; } private V remove(Node node){ if (node == null){ return null; } size--; V oldValue = node.value; // 判断度为2 if (node.hasTwoChildren()){ // 获取后继节点 Node s = successor(node); // 后继节点的值覆盖当前节点的值 node.key = s.key; node.value = s.value; // 将node指向s节点 node = s; } // 获取被删除节点的子节点,如果左子节点为空则获取右子节点; // 如果子节点都为空,则表示该节点是叶子节点返回null。 Node relacement = node.left != null ? node.left : node.right; if (relacement != null){ // node 是度为1的节点 // 更改parent relacement.parent = node.parent; // 更改parent的left(right)的指向 if (node.parent == null){ // node是度为1的根节点。 root = relacement; }else if (node == node.parent.left){ // 被删除节点是父节点的左子节点 node.parent.left = relacement; } else { // 被删除节点是父节点的右子节点 node.parent.right = relacement; } // 删除之后处理 afterRemove(relacement); }else if(node.parent == null){ // node是叶子节点并且是根节点 root = null; // 删除之后处理 afterRemove(node); }else { //node 是普通叶子节点 if (node == node.parent.left){ // 当前节点是父节点的右子节点 node.parent.left = null; }else { // 是父节点的左子节点 node.parent.right = null; } // 删除之后处理 afterRemove(node); } return oldValue; } private Node successor(Node node){ if (node == null) { return null; } Node prev = node.right; // 前驱在左子树中 if (prev != null){ while (prev.left != null){ prev = prev.left; } return prev; } // 前驱在祖父节点中 while (node.parent != null && node == node.parent.right){ node = node.parent; } return node.parent; } private void afterRemove(Node node) { // 如果删除的节点是红色 // 或者 用以取代删除节点的子节点是红色 if (isRed(node)) { black(node); return; } Node parent = node.parent; // 删除的是根节点 if (parent == null) { return; } // 删除的是黑色叶子节点【下溢】 // 判断被删除的node是左还是右 boolean left = parent.left == null || node.isLeftChild(); Node 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); } } } private static class Node { K key; V value; boolean color = RED; Node left; Node right; Node parent; public Node(K key, V value, Node parent) { this.key = key; this.value = value; this.parent = parent; } public boolean isLeaf() { return left == null && right == null; } public boolean hasTwoChildren() { return left != null && right != null; } public boolean isLeftChild() { return parent != null && this == parent.left; } public boolean isRightChild() { return parent != null && this == parent.right; } public Node sibling() { if (isLeftChild()) { return parent.right; } if (isRightChild()) { return parent.left; } return null; } } }
把Map的value去掉就是一个Set。
- 使用TreeMap实现Set:
public class TreeSetOfMapimplements Set { Map map = new TreeMap<>(); @Override public int size() { return map.size(); } @Override public boolean isEmpty() { return map.isEmpty(); } @Override public void clear() { map.clear(); } @Override public boolean contains(E e) { return map.containsKey(e); } @Override public void add(E e) { map.put(e,null); } @Override public void remove(E e) { map.remove(e); } @Override public void traversal(Visitor visitor) { map.traversal(new Map.Visitor () { @Override protected boolean visit(E e, Object o) { return visitor.visit(e); } }); } }
- 关于Java中集合和映射可以查看:Map和Set。



