TreeMap,ThreeSet源码
ThreeSet
ThreeSet的底层就是ThreeMap
public TreeSet() { this(new TreeMap<E,Object>()); }
ThreeMap
1.ThreeMap参数
//比较器 private final Comparator<? super K> comparator; //根节点 private transient Entry<K,V> root; //长度 private transient int size = 0; //对树进行结构修改的次数 private transient int modCount = 0;
2.Entry参数
K key;//键 V value;//值 Entry<K,V> left;//左子节点 Entry<K,V> right;//右子节点 Entry<K,V> parent;//父节点 boolean color = BLACK; //节点颜色
3.构造
public TreeMap() { comparator = null; }
4.put方法
public V put(K key, V value) { //获取根节点 Entry<K,V> t = root; //第一次进入,根节点为null if (t == null) { //验证key是否为空 compare(key, key); // type (and possibly null) check //根据键值创建根节点 root = new Entry<>(key, value, null); //size加一 size = 1; //操作次数加加 modCount++; return null; } int cmp; //创建父节点 Entry<K,V> parent; //获得比较器 ,比较器在无参初始化的时候就是null,地下也没有给比较器赋值的地方 Comparator<? super K> cpr = comparator; //判断比较器是否为空 if (cpr != null) { do { parent = t; cmp = cpr.compare(key, t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } else {//比较器为空进入 //key为空抛出异常 if (key == null) throw new NullPointerException(); //这个注解是取消代码中的警告 @SuppressWarnings("unchecked") //获取key Comparable<? super K> k = (Comparable<? super K>) key; //循环执行找到当前节点的父节点 do { //根节点给父节点 parent = t; //用当前的k和根节点的key进行比较 前面的小返回 负数 cmp = k.compareTo(t.key); //k小于根节点的key 将根节点的左子节点给根节点 if (cmp < 0) t = t.left; else if (cmp > 0) //k 大于根节点的key 将根节点的右子节点给根节点 t = t.right; else //相等的话证明是一致的key 直接修改根的值,并跳出循环 return t.setValue(value); //根不为空就向下进行循环,一直找到最后的节点为止 } while (t != null); } //根据key value 和父节点 创建一个节点 Entry<K,V> e = new Entry<>(key, value, parent); //根据上面的对比决定新节点放到左面还是右面 if (cmp < 0) parent.left = e; else parent.right = e; //执行旋转 fixAfterInsertion(e); size++; modCount++; return null; }
验证key是否为空
final int compare(Object k1, Object k2) { return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2) : comparator.compare((K)k1, (K)k2); }
执行旋转
//parentOf(x) 找到当前节点的父节点 //leftOf(x) 找到当前节点的左节点 //rightOf(x)找到当前节点的右节点 //colorOf(x)找到当前节点的颜色 //setColor(x,color) 设置当前节点的颜色 //传入的是当前put的节点 private void fixAfterInsertion(Entry<K,V> x) { //将当前节点设置为红色 x.color = RED; //判断当前节点不是null 不是根节点 并且父节点的颜色是红色 while (x != null && x != root && x.parent.color == RED) { //判断当前节点的父节点是 当前节点的爷爷节点的左边 if (parentOf(x) == leftOf(parentOf(parentOf(x)))) { //得到当前节点的爷爷节点的右节点,也就是叔叔节点 Entry<K,V> y = rightOf(parentOf(parentOf(x))); //判断叔叔节点是红色 if (colorOf(y) == RED) { //将父节点设置为黑色 setColor(parentOf(x), BLACK); //将叔叔节点转为黑色 setColor(y, BLACK); //将祖父节点设置为红色 setColor(parentOf(parentOf(x)), RED); 将祖父节点给当前节点,进行循环再次旋转 x = parentOf(parentOf(x)); } else {//当前节点的父节点在爷爷节点的右面 //判断当前节点在父节点的右面 if (x == rightOf(parentOf(x))) { //将父节点给当前节点 x = parentOf(x); //对父节点进行左旋 rotateLeft(x); } //将当前节点设置为黑色 setColor(parentOf(x), BLACK); //将祖父节点设置为红色 setColor(parentOf(parentOf(x)), RED); //对祖父节点进行右旋 rotateRight(parentOf(parentOf(x))); } } else {//当前节点的父节点不在左面 祖父节点不是红色 //得到叔叔节点 Entry<K,V> y = leftOf(parentOf(parentOf(x))); //判断叔叔节点是否是红色 if (colorOf(y) == RED) { //将父节点设置为黑色 setColor(parentOf(x), BLACK); //将叔叔节点设置为黑色 setColor(y, BLACK); //将爷爷节点设置为红色 setColor(parentOf(parentOf(x)), RED); //将爷爷节点给当前节点,进入循环再次旋转 x = parentOf(parentOf(x)); } else { //判断当前节点在父节点的左面 if (x == leftOf(parentOf(x))) { //父节点等于当前节点 x = parentOf(x); //对父节点进行右旋 rotateRight(x); } //将父节点设置为黑色 setColor(parentOf(x), BLACK); //将爷爷节点设置为红色 setColor(parentOf(parentOf(x)), RED); //将爷爷节点进行左旋 rotateLeft(parentOf(parentOf(x))); } } } //将根节点设为黑色 root.color = BLACK; }
parentOf(x) 找到当前节点的父节点
private static <K,V> Entry<K,V> parentOf(Entry<K,V> p) { return (p == null ? null: p.parent); }
leftOf(x) 找到当前节点的左节点
private static <K,V> Entry<K,V> leftOf(Entry<K,V> p) { return (p == null) ? null: p.left; }
rightOf(x)找到当前节点的右节点
private static <K,V> Entry<K,V> rightOf(Entry<K,V> p) { return (p == null) ? null: p.right; }
colorOf(x)找到当前节点的颜色
private static <K,V> boolean colorOf(Entry<K,V> p) { return (p == null ? BLACK : p.color); }
setColor(x,color) 设置当前节点的颜色
private static <K,V> void setColor(Entry<K,V> p, boolean c) { if (p != null) p.color = c; }
rotateLeft 进行左旋
/** From CLR */ private void rotateLeft(Entry<K,V> p) { if (p != null) { Entry<K,V> r = p.right; p.right = r.left; if (r.left != null) r.left.parent = p; r.parent = p.parent; if (p.parent == null) root = r; else if (p.parent.left == p) p.parent.left = r; else p.parent.right = r; r.left = p; p.parent = r; } }
rotateRight 进行右旋
/** From CLR */ private void rotateRight(Entry<K,V> p) { if (p != null) { Entry<K,V> l = p.left; p.left = l.right; if (l.right != null) l.right.parent = p; l.parent = p.parent; if (p.parent == null) root = l; else if (p.parent.right == p) p.parent.right = l; else p.parent.left = l; l.right = p; p.parent = l; } }