public void delete(K key) {
        //Lookup the node we're trying to delete (Woo parent references!~)
        RBTreeNode<K, V> node = lookupNode(key);
        if (node == null) {
            //If the node we're trying to delete isn't actually in the tree
            //Then return, because we don't have anything to do.
            return;
        }
        //If the node we're removing has both children...
        if (node.left != null && node.right != null) {
            //Grab rightmost left child (predecessor)
            RBTreeNode<K, V> next = maximumNode(node.left);
            //Replace the node we're trying to delete with the rightmost child (in terms of values/keys, children still there.)
            node.key = next.key;
            node.value = next.value;
            //Then swap the node reference we're trying to delete with the rightmost child reference (which is fine now)
            node = next;
        }

        //Make sure we have at least one null child
        assert node.left == null || node.right == null;
        RBTreeNode<K, V> child;
        //Let child be our only child node if right is null,
        //Else the right child
        if (node.right == null) {
            child = node.left;
        } else {
            child = node.right;
        }
        //If we're a black node
        if (nodeColor(node) == Color.BLACK) {
            //Replace our color with child's color
            node.color = nodeColor(child);
            //Then go on and fix the tree.
            deleteCase1(node);
        }
        //Fix the children/parent references (actual deletion occurs here, for the most part)
        replaceNode(node, child);

        //If root ended up red after all this
        if (nodeColor(root) == Color.RED) {
            //Fix it.
            root.color = Color.BLACK;
        }

        verifyProperties();
    }