TreeMap:基于紅黑樹實現(xiàn)的一個有序的Map實現(xiàn)類.這個有序的維護是通過key實現(xiàn)的Comparable接口或者是在構(gòu)造時傳入的Comparator類來實現(xiàn)它的一個排序規(guī)則的.TreeMap的實現(xiàn)保證了containsKey(),put(),get(),remove()操作的時間復雜度均是log(n)(n是樹上的entry數(shù)).TreeMap是非線程安全類,如果多個線程同時訪問來修改treemap的結(jié)構(gòu)(改變結(jié)構(gòu)是指執(zhí)行了添加或者刪除操作,如果改變一個已經(jīng)存在的key的值這類操作則不算是改變結(jié)構(gòu)),那么必須在外部來保證對這個treemap的同步訪問.
如果要對一個treemap進行同步訪問,我們也可以使用java中提供的同步包裝類來實現(xiàn)同步,例如:
SortedMap m = Collections.synchronizedSortedMap(new TreeMap(...));
下面我們來看看TreeMap中的Entry是一種什么樣的結(jié)構(gòu):
static final class Entry<K,V> implements Map.Entry<K,V> {
K key;
V value;
Entry<K,V> left = null; // 左子樹
Entry<K,V> right = null; // 右子樹
Entry<K,V> parent; // 父節(jié)點
boolean color = BLACK; // 本節(jié)點的顏色(紅黑兩種)
Entry(K key, V value, Entry<K,V> parent) {
this.key = key;
this.value = value;
this.parent = parent;
}
}
類定義
public class TreeMap<K,V>
extends AbstractMap<K,V>
implements NavigableMap<K,V>, Cloneable, java.io.Serializable
成員變量
修飾符 | 變量名 | 作用 |
---|---|---|
private final Comparator<? super K> | comparator | 排序比較類 |
private transient Entry<K,V> | root = null | 紅黑樹的根節(jié)點 |
private transient int | size = 0 | entry數(shù)量 |
private transient int | modCount = 0 | 記錄改變結(jié)構(gòu)的次數(shù) |
方法講解-只講解put和get操作
添加元素 put()
/**
* 1. 首先判斷根元素是否為空,也就是當前put進來的entry是否是第一次操作
* 2. 如果是第一次put,則直接創(chuàng)建entry并賦值給root
* 3. 如果不是第一次put(也就是root不為null),則獲取比較器
* 4. 將新增的key從根節(jié)點開始比較,
* 小于根節(jié)點則繼續(xù)跟當前節(jié)點的左子樹的根節(jié)點比較;
* 大于根節(jié)點則繼續(xù)跟當前節(jié)點的右子樹的根節(jié)點比較;
* 如果等于當前節(jié)點則直接用value替換原來的值并返回原來的值
* 5. 最后如果不是執(zhí)行的替換操作,而是執(zhí)行的插入則要重新調(diào)整樹的結(jié)構(gòu),
* 讓新樹符合紅黑樹的規(guī)則.
**/
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);
}
// 遍歷完成,找到新增節(jié)點放置的位置
Entry<K,V> e = new Entry<>(key, value, parent);
if (cmp < 0) // 比父節(jié)點小,放在左子樹
parent.left = e;
else // 大,放在右子樹
parent.right = e;
// 重新調(diào)整樹使之符合紅黑樹的規(guī)則
// (此過程比較復雜,需了解紅黑樹算法規(guī)則,在此暫不分析)
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
獲取元素get()
TreeMap的get()操作就是通過比較循環(huán)獲取左右子樹比較的一個過程,直到找到對應的節(jié)點
public V get(Object key) {
Entry<K,V> p = getEntry(key);
return (p==null ? null : p.value);
}
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();
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) {
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;
}