TreeSet是对HashSet的排序,可以指定比较器,默认自然升序排序
提供众多方法。
add方法:
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
使用NavigableMap的put方法。
private transient NavigableMap<E,Object> m;
此方法由TreeMap进行实现。
输入元素作为键值,新建的对象值作为值。元素插入采用树形结构判断
static final class Entry<K,V> implements Map.Entry<K,V> {
K key;
V value;
Entry<K,V> left;
Entry<K,V> right;
Entry<K,V> parent;
boolean color = BLACK;
public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
compare(key, key); // type (and possibly null) check
//定义首个插入的数据作为根节点
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
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 {
//自然升序排序,锁定最底层节点
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) key;
//循环进行,直到加入数据需要放置的节点为空为止
do {
//进行比较,
parent = t;
cmp = k.compareTo(t.key);
//如果元素小于根节点,则根节点变为下一层的左节点
if (cmp < 0)
t = t.left;
//如果元素大于根节点,则根节点变为下一层的右节点
else if (cmp > 0)
t = t.right;
else
//如果相等,直接赋值,不增加节点
return t.setValue(value);
} while (t != null);
}
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;
}
元素的遍历:规则为左中右原则:以下图为例说明
最左侧节点为3,中间节点为5,右节点为8,其中右节点8又是底层的中间节点,其左节点为7,右节点为9
排序为:3,5,8
3,5,7,8,9.
然后是中间节点12.
右侧节点14,又是底层节点的中间节点
排序为:12,14
12,13,14,15
最终排序为:3,5,7,8,9,12,13,14,15
删除元素
public V remove(Object key) {
//以键值为依据,获取键值对应的节点
Entry<K,V> p = getEntry(key);
if (p == null)
return null;
V oldValue = p.value;
//删除键值对应的节点
deleteEntry(p);
//返回键值对应的值
return oldValue;
}
------------------getEntry(key)--------------------------
final Entry<K,V> getEntry(Object key) {
// Offload comparator-based version for sake of performance
if (comparator != null)
return getEntryUsingComparator(key);
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) key;
Entry<K,V> p = root;
//循环查找p对应的节点位置
while (p != null) {
int cmp = k.compareTo(p.key);
if (cmp < 0)
p = p.left;
else if (cmp > 0)
p = p.right;
else
return p;
}
return null;
}
------------------- deleteEntry(p);----------------------------
private void deleteEntry(Entry<K,V> p) {
modCount++;
size--;
// If strictly internal, copy successor's element to p and then make p
// point to successor.
if (p.left != null && p.right != null) {
Entry<K,V> s = successor(p);
p.key = s.key;
p.value = s.value;
p = s;
} // p has 2 children
// Start fixup at replacement node, if it exists.
//先判断左侧是否为空
Entry<K,V> replacement = (p.left != null ? p.left : p.right);
if (replacement != null) {
// Link replacement to parent
//左侧节点的父节点变为待删除节点的父节点
replacement.parent = p.parent;
//如果删除的节点为根节点
if (p.parent == null)
//将左子节点作为跟节点
root = replacement;
else if (p == p.parent.left)
p.parent.left = replacement;
else
p.parent.right = replacement;
// Null out links so they are OK to use by fixAfterDeletion.
p.left = p.right = p.parent = null;
// Fix replacement
if (p.color == BLACK)
fixAfterDeletion(replacement);
} else if (p.parent == null) { // return if we are the only node.
root = null;
} else { // No children. Use self as phantom replacement and unlink.
if (p.color == BLACK)
fixAfterDeletion(p);
//如果待删除的节点没有子节点,直接将对应的位置赋值null
if (p.parent != null) {
if (p == p.parent.left)
p.parent.left = null;
else if (p == p.parent.right)
p.parent.right = null;
p.parent = null;
}
}
}