1. TreeSet保证元素唯一性和自然排序的原理和图解
2. TreeSet唯一性以及有序性底层剖析:
通过观察TreeSet的add()方法,我们知道最终要看TreeMap的put()方法。
跟踪进入源码:
interface Collection {...} interface Set extends Collection {...} interface NavigableMap { } class TreeMap implements NavigableMap {
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();
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;
}
} class TreeSet implements Set {
private transient NavigableMap<E,Object> m; public TreeSet() {
this(new TreeMap<E,Object>());
} public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
}
总结:
真正的比较是依赖于元素的compareTo()方法,而这个方法是定义在 Comparable里面的。所以,你要想重写该方法,就必须是先 Comparable接口。这个接口表示的就是自然排序。
通过观察TreeSet的底层源码发现,TreeSet的add(E e)方法,底层是根据实现Comparable的方式来实现的唯一性,通过compare(Object o)的返回值是否为0来判断是否为同一元素。
compare() == 0,元素不入集合。
compare() > 0 ,元素入右子树。
compare() < 0,元素入左子树。
而对其数据结构:自平衡二叉树做前(常用)、中、后序遍历即可保证TreeSet的有序性。