TreeMap是一個二叉樹的數據結構;TreeMap不允許出現相同的鍵。
源碼解析:

一:
這是TreeMap的put源碼。
可以看出有一個泛型對象實體Entry,Entry里面維持一個 左、右子樹跟父樹 的對象屬性。依靠這個實體完成樹形結構的構建,包括hashCode跟equals的生成。
TreeMap首先將第一個要put的值設為根節點,后續要put的值根據 
來比較該對象應該要放置的位置,由於compare返回類型是int,所以比較器返回三種情況 > 0、< 0、== 0.

如果比較后獲取的值< 0,則將該樹的左子樹設置為當前樹,> 0 則為右子樹,== 0 則將該樹的值設置為當前要put的值,這也就是說明為什么TreeMap中,如果有相同的鍵put,
后續的鍵值會覆蓋掉前邊鍵的值。
然后

根據比較器將 當前節點 設置為父節點的左子樹還是右子樹
這樣put操作也就形成了一棵二叉樹!
二:
我們來看get源碼。
public V get(Object key) {
Entry<K,V> p = getEntry(key);
return (p==null ? null : p.value);
}
具體操作位於getEntry中。
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;
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;
}
final Entry<K,V> getEntryUsingComparator(Object key) {
@SuppressWarnings("unchecked")
K k = (K) key;
Comparator<? super K> cpr = comparator;
if (cpr != null) {
Entry<K,V> p = root;
while (p != null) {
int cmp = cpr.compare(k, p.key);
if (cmp < 0)
p = p.left;
else if (cmp > 0)
p = p.right;
else
return p;
}
}
return null;
}
可以看得出來,這就是遍歷二叉樹,最終比較器獲得的值==0的也就是相等的節點對象就是要獲取的值。
大家應該可以看得出來,如果比較器出現 == 0 的情況才會返回,如果!= 0 則一直會進行遍歷。
來看一個問題:

比較器是比較兩個字符串的長度。
我們的put操作是沒有問題的,因為鍵沒有相同的,而且只存在兩種類型>0或<0,所以所有的值都是分布在左右子樹上;
但是get操作,那么問題來了,由於比較器返回三種類型的值>0、<0 、== 0
所以一旦存在有兩個鍵的length相等,那么可以想一下,
每當到達匹配到相同值的時候,由於比較器返回的是>0或<0,不會直接return,所以這個操作會繼續do-while循環,

當比較器的值相等的時候就會才會直接返回當前節點對象,但是毫無疑問該節點是沒有值的,所以總是會返回null。
使用TreeMap首先需要 鍵唯一;
如果出現在比較器中的返回值對於0有三種情況,
put操作沒有問題,會生成完整的二叉樹,
get操作有問題,就會出現為null的情況!
