1. 简单函数系列
/* 返回元素个数 */
public int size() { return size; }
/* 是否包含指定的key */
public boolean containsKey(Object key) { return getEntry(key) != null; }
/* 是否包含指定的value值,从 getFirstEntry()获取首节点(最小节点)开始 */
public boolean containsValue(Object value) {
/* 查找 e 的后继节点 */
for(Entry<K,V> e = getFirstEntry(); e != null; e = successor(e))
if (valEquals(value, e.value))
return true;
return false;
}
/* 返回当前的比较器 */
public Comparator<? super K> comparator() {
return comparator;
}
2. put(K key, V value)
- 若key存在,更新新值为 value,返回oldValue,若不存在,添加新节点,返回 null
public V put(K key, V value) {
Entry<K,V> t = root;
/* 空树的节点添加 */
if (t == null) {
/* 类型检查 */
compare(key, key);
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// 比较器 == null 判断,不为 null 直接使用,为null 将key强转类型
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,返回null */
size++;
modCount++;
return null;
}
3. putAll(Map<? extends K, ? extends V> map)
- 添加 map集合,使用TreeMap的排序方法
public void putAll(Map<? extends K, ? extends V> map) {
int mapSize = map.size();
/* 当前TreeMap size 为0 && mapSize 不为 0 && map 是SortedMap的实例 */
if (size==0 && mapSize!=0 && map instanceof SortedMap) {
/* 获取比较器 */
Comparator<?> c = ((SortedMap<?,?>)map).comparator();
/* 若c 与 TreeMap使用的比较器相同 */
if (c == comparator || (c != null && c.equals(comparator))) {
++modCount; // 更新 modCount
try {
/* 添加所有的元素,后面详讲 */
buildFromSorted(mapSize, map.entrySet().iterator(),
null, null);
} catch (java.io.IOException cannotHappen) {
} catch (ClassNotFoundException cannotHappen) {
}
return;
}
}
/* 这里调用父类的putAll(),循环内部还是调用的put()方法 */
super.putAll(map);
}
4. get(Object key)
- 获取指定key 的value值
/* 获取指定key 的value值 */
public V get(Object key) {
/* 调用getEntry 获取节点 */
Entry<K,V> p = getEntry(key);
return (p==null ? null : p.value);
}
/* 根据key值获取 entry节点,找不到返回null */
final Entry<K,V> getEntry(Object key) {
/* 当前比较器存在,使用指定的比较器查找 */
if (comparator != null)
return getEntryUsingComparator(key);
/* null 异常检测 */
if (key == null)
throw new NullPointerException();
/* 强转key的类型,使用强转的比较器(默认自然排序)进行比较 */
@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;
}
5. remove(Object key)
- 删除指定的key对应的节点,找不到返回 null
public V remove(Object key) {
/* 获取key对应的节点,找不到返回null */
Entry<K,V> p = getEntry(key);
if (p == null)
return null;
/* 找到获取旧值,删除节点,返回旧值 */
V oldValue = p.value;
deleteEntry(p); // 后面详讲
return oldValue;
}
6. clear()
- 清空当前treemap,直接将 root 置为null
public void clear() {
modCount++;
size = 0;
root = null;
}
7. 小总结
import java.util.TreeMap;
public class TreeMapTest01 {
public static void main(String[] args) {
TreeMap<Integer, Integer> treeMap = new TreeMap<>((o1, o2)-> o1.compareTo(o2));
for(int i = 1; i <= 4; i++) {
treeMap.put(i, i);
}
System.out.println("now treemap.size(): " + treeMap.size());
System.out.println("now treemap.comparator(): " + treeMap.comparator());
System.out.println("now treemap: " + treeMap);
System.out.println("====================================");
TreeMap<Integer, Integer> treeMap01 = new TreeMap<>((o1, o2)-> o2.compareTo(o1));
for(int i = 5; i <= 8; i++) {
treeMap01.put(i, i);
}
System.out.println("now treemap01.size(): " + treeMap01.size());
System.out.println("now treemap01.comparator(): " + treeMap01.comparator());
System.out.println("now treemap01: " + treeMap01);
System.out.println("====================================");
treeMap.putAll(treeMap01);
System.out.println("now treemap.size(): " + treeMap.size());
System.out.println("putAll(treemap01), now treemap: " + treeMap);
System.out.println("=====================================");
System.out.println("treeMap.get(1): " + treeMap.get(1));
System.out.println("treeMap.get(10): " + treeMap.get(10));
System.out.println("treeMap.getOrDefault(1,10): " + treeMap.getOrDefault(1, 10));
System.out.println("treeMap.getOrDefault(10,10): " + treeMap.getOrDefault(10, 10));
System.out.println("=====================================");
System.out.println("treeMap.containsKey(1): " + treeMap.containsKey(1));
System.out.println("treeMap.containsKey(10): " + treeMap.containsKey(10));
System.out.println("treeMap.containsValue(1): " + treeMap.containsValue(1));
System.out.println("treeMap.containsValue(10): " + treeMap.containsValue(10));
System.out.println("=====================================");
System.out.println("now treemap: " + treeMap);
treeMap.clear();
System.out.println("treeMap.clear(), now treemap: " + treeMap);
}
}
导航方法相关
8. 简单函数合集
/* 获取节点中的key,具有 null异常判断 */
static <K> K key(Entry<K,?> e) {
if(e==null)
throw new NoSuchElementException();
return e.key;
}
/* 获取节点中的key,节点为null返回null,不会报错 */
static <K,V> K keyOrNull(TreeMap.Entry<K,V> e) {
return (e == null) ? null : e.key;
}
/* 获取第一个节点的 key */
public K firstKey() {
return key(getFirstEntry());
}
/* 获取最后一个节点的 key */
public K lastKey() {
return key(getLastEntry());
}
9 -12 为内部方法,防止外部修改entry节点。
9. getCeilingEntry(K key)
- 获取 >= key 的最小节点,找不到返回 null
final Entry<K,V> getCeilingEntry(K key) {
Entry<K,V> p = root;
while (p != null) {
int cmp = compare(key, p.key);
/* key < p.key 则往左找,若p左子节点为null,则 p 为大于 key 的最小节点 */
if (cmp < 0) {
if (p.left != null)
p = p.left;
else
return p;
} else if (cmp > 0) { // key > p.key
/* 往右查找 */
if (p.right != null) {
p = p.right;
} else {
/* 这里的逻辑有点绕,但总体分为以下两种,以root节点为例
* 1. 从根节点出发,没有过某个节点的p.key > key 的情况,
* 直至最大右节点也找不到比key大的节点,则返回null
* 2. 从根节点出发,至少经历过1次某个节点的p.key > key,假设这个节点为root
* 以root.left出发,直至最大节点,所有节点的p.key都比key小,那么大于key的最小节点则为 root */
Entry<K,V> parent = p.parent;
Entry<K,V> ch = p;
while (parent != null && ch == parent.right) {
ch = parent;
parent = parent.parent;
}
return parent;
}
} else
/* key == p.key 则返回 p */
return p;
}
return null;
}
10. getHigherEntry(K key)
- 获取 > key 的最小节点,找不到返回 null,与 getCeilingEntry 的差别为Node.key == key 时继续往右比较
final Entry<K,V> getHigherEntry(K key) {
Entry<K,V> p = root;
while (p != null) {
int cmp = compare(key, p.key);
if (cmp < 0) {
if (p.left != null)
p = p.left;
else
return p;
} else {
if (p.right != null) {
p = p.right;
} else {
Entry<K,V> parent = p.parent;
Entry<K,V> ch = p;
while (parent != null && ch == parent.right) {
ch = parent;
parent = parent.parent;
}
return parent;
}
}
}
return null;
}
11. getFloorEntry(K key)
- 获取 <= key 的最大节点,找不到返回 null
final Entry<K,V> getFloorEntry(K key) {
Entry<K,V> p = root;
while (p != null) {
int cmp = compare(key, p.key);
/* key > p.key,往右查找是否有 p.key 与 key 之间的节点 */
if (cmp > 0) {
if (p.right != null)
p = p.right;
else
return p;
/* key < p.key,往左查找 */
} else if (cmp < 0) {
if (p.left != null) {
p = p.left;
} else {
/* 这里的逻辑有点绕,但总体分为以下两种,以root节点为例
* 1. 从根节点出发,没有过某个节点的p.key < key 的情况,
* 直至最小左节点也找不到比key小的节点,则返回null
* 2. 从根节点出发,至少经历过1次某个节点的p.key < key,假设这个节点为root
* 以root.right出发,直至最小节点,所有节点的p.key都比key大,那么小于key的最大节点则为 root */
Entry<K,V> parent = p.parent;
Entry<K,V> ch = p;
while (parent != null && ch == parent.left) {
ch = parent;
parent = parent.parent;
}
return parent;
}
} else
return p;
}
return null;
}
12. getLowerEntry(K key)
- 获取 < key 的最大节点,找不到返回 null,与 getFloorEntry 的差别为Node.key == key 时继续往左比较
final Entry<K,V> getLowerEntry(K key) {
Entry<K,V> p = root;
while (p != null) {
int cmp = compare(key, p.key);
if (cmp > 0) {
if (p.right != null)
p = p.right;
else
return p;
} else {
if (p.left != null) {
p = p.left;
} else {
Entry<K,V> parent = p.parent;
Entry<K,V> ch = p;
while (parent != null && ch == parent.left) {
ch = parent;
parent = parent.parent;
}
return parent;
}
}
}
return null;
}
13. getFirstEntry()、getLastEntry()
/* 获取第一个节点 */
final Entry<K,V> getFirstEntry() {
Entry<K,V> p = root;
if (p != null)
while (p.left != null)
p = p.left;
return p;
}
/* 获取最后一个节点 */
final Entry<K,V> getLastEntry() {
Entry<K,V> p = root;
if (p != null)
while (p.right != null)
p = p.right;
return p;
}
14. firstEntry()、lastEntry()、pollFirstEntry()、pollLastEntry()
- 先来看 exportEntry,导出节点,这里是生成一个新节点导出,防止原有节点受到破坏
/* e不为null则生成一个 SimpleImmutableEntry */
static <K,V> Map.Entry<K,V> exportEntry(TreeMap.Entry<K,V> e) {
return (e == null) ? null :
new AbstractMap.SimpleImmutableEntry<>(e);
}
/* 获取第一个节点,底层调用getFirstEntry()获取节点后,生成返回的新节点 */
public Map.Entry<K,V> firstEntry() {
return exportEntry(getFirstEntry());
}
/* 获取最后一个节点,底层调用getLastEntry()获取节点后,生成返回的新节点 */
public Map.Entry<K,V> lastEntry() {
return exportEntry(getLastEntry());
}
/* 获取并删除第一个节点,底层调用getFirstEntry()获取节点后,生成返回的新节点 */
public Map.Entry<K,V> pollFirstEntry() {
Entry<K,V> p = getFirstEntry();
Map.Entry<K,V> result = exportEntry(p);
if (p != null)
deleteEntry(p); // 删除节点
return result;
}
/* 获取并删除最后一个节点,底层调用getLastEntry()获取节点后,生成返回的新节点 */
public Map.Entry<K,V> pollLastEntry() {
Entry<K,V> p = getLastEntry();
Map.Entry<K,V> result = exportEntry(p);
if (p != null)
deleteEntry(p); // 删除节点
return result;
}
15. lowerKey(K key)、floorKey(K key)、floorKey(K key)、higherKey(K key)
- 底层调用对应的getXXXEntry,获取节点后进而获取key
/* 获取 < key 的最大节点的key */
public K lowerKey(K key) {
return keyOrNull(getLowerEntry(key));
}
/* 获取 <= key 的最大节点的key */
public K floorKey(K key) {
return keyOrNull(getFloorEntry(key));
}
/* 获取 >= key 的最小节点的key */
public K ceilingKey(K key) {
return keyOrNull(getCeilingEntry(key));
}
/* 获取 > key 的最小节点的key */
public K higherKey(K key) {
return keyOrNull(getHigherEntry(key));
}
16. lowerEntry(K key)、floorEntry(K key)、ceilingEntry(K key)、 higherEntry(K key)
- 底层调用对应的getXXXEntry,获取 entry 节点
/* 获取 < key 的最大节点,找不到返回 null */
public Map.Entry<K,V> lowerEntry(K key) {
return exportEntry(getLowerEntry(key));
}
/* 获取 <= key 的最大节点,找不到返回 null */
public Map.Entry<K,V> floorEntry(K key) {
return exportEntry(getFloorEntry(key));
}
/* 获取 >= key 的最小节点,找不到返回 null */
public Map.Entry<K,V> ceilingEntry(K key) {
return exportEntry(getCeilingEntry(key));
}
/* 获取 > key 的最小节点,找不到返回 null */
public Map.Entry<K,V> higherEntry(K key) {
return exportEntry(getHigherEntry(key));
}
17 总结
import java.util.TreeMap;
public class TreeMapTest02 {
public static void main(String[] args) {
TreeMap<Integer, Integer> treeMap = new TreeMap<>();
for(int i = 1; i <= 10; i++) {
treeMap.put(i, i);
}
System.out.println("now treemap: " + treeMap);
System.out.println("treeMap.firstKey(): " + treeMap.firstKey());
System.out.println("treeMap.firstEntry(): " + treeMap.firstEntry());
System.out.println("treeMap.lastKey(): " + treeMap.lastKey());
System.out.println("treeMap.lastEntry(): " + treeMap.lastEntry());
System.out.println("=======================");
System.out.println("now treemap: " + treeMap);
System.out.println("treeMap.pollFirstEntry(): " + treeMap.pollFirstEntry());
System.out.println("now treemap: " + treeMap);
System.out.println("treeMap.pollLastEntry(): " + treeMap.pollLastEntry());
System.out.println("=======================");
System.out.println("now treemap: " + treeMap);
System.out.println("treeMap.lowerKey(5): " + treeMap.lowerKey(5));
System.out.println("treeMap.lowerEntry(5): " + treeMap.lowerEntry(5));
System.out.println("treeMap.floorKey(5): " + treeMap.floorKey(5));
System.out.println("treeMap.floorKey(5): " + treeMap.floorKey(5));
System.out.println("=======================");
System.out.println("treeMap.ceilingKey(5): " + treeMap.ceilingKey(5));
System.out.println("treeMap.ceilingEntry(5): " + treeMap.ceilingEntry(5));
System.out.println("treeMap.higherKey(5): " + treeMap.higherKey(5));
System.out.println("treeMap.higherEntry(5): " + treeMap.higherEntry(5));
}
}