从源码理解TreeMap.java
package java.util;
import java.io.Serializable;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
/**
* 基于红黑树的NavigableMap接口实现
* Map是根据关键字的自然比较序排序,或是根据创建时初始化的比较器的比较结果排序
* 这个实现保证提供log(n)时间的操作:containsKey、get、put、remove
* 树形Map的顺序是保持不变的,和其他有序Map一样,不管有没有提供显式的比较器,而且必须和equals兼容
* 注意,这个实现是不支持并发访问的。需要外部显式同步,如下:
* SortedMap m = Collections.synchronizedSortedMap(new TreeMap(...));
* 所有集合视图返回的迭代器都是快速失败的(fail-fast)
*/
public class TreeMap<K,V>
extends AbstractMap<K,V>
implements NavigableMap<K,V>, Cloneable, java.io.Serializable
{
/**
* 用于保持顺序的比较器,如果为空,使用自然序保持Key的顺序
*/
private final Comparator<? super K> comparator;
//根节点
private transient Entry<K,V> root = null;
/**
* 树中的结点数量
*/
private transient int size = 0;
/**
* 用于记录结构上的改变次数
*/
private transient int modCount = 0;
/**
* 构造方法一,默认构造方法,Comparator为空,即采用自然序维持TreeMap中结点的顺序
*/
public TreeMap() {
comparator = null;
}
/**
* 构造方法二,提供指定的比较器,如果为空,还是自然序
*/
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
/**
* 构造方法三,采用自然序维持TreeMap中结点的顺序,同时将传入的Map中的内容添加到TreeMap中
*/
public TreeMap(Map<? extends K, ? extends V> m) {
comparator = null;
putAll(m);
}
/**
* 构造方法四,接受SortedMap参数,根据SortedMap的比较器维持TreeMap中的结点顺序,
* 同时通过buildFromSorted(int size, Iterator it,
* java.io.ObjectInputStream str, V defaultVal)方法将SortedMap中的 内容添加到TreeMap中
*/
public TreeMap(SortedMap<K, ? extends V> m) {
comparator = m.comparator();
try {
buildFromSorted(m.size(), m.entrySet().iterator(), null, null);
} catch (java.io.IOException cannotHappen) {
} catch (ClassNotFoundException cannotHappen) {
}
}
// 查询操作
/**
* 返回Map中键值对数目
*/
public int size() {
return size;
}
/**
* 是否包含指定关键字
*/
public boolean containsKey(Object key) {
return getEntry(key) != null;
}
/**
* 是否包含指定值,时间复杂度和Map大小成正比
*/
public boolean containsValue(Object value) {
//通过e = successor(e)实现对树的遍历
for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e))
//判断结点值是否和value相等
if (valEquals(value, e.value))
return true;
//若没有,返回false
return false;
}
/**
* 返回指定关键字的值,没有则返回null
* 返回null不代表不存在,也有可能是值就是null
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key is null
* and this map uses natural ordering, or its comparator
* does not permit null keys
*/
public V get(Object key) {
Entry<K,V> p = getEntry(key);
return (p==null ? null : p.value);
}
public Comparator<? super K> comparator() {
return comparator;
}
/**
* @throws NoSuchElementException {@inheritDoc}
*/
public K firstKey() {
return key(getFirstEntry());
}
/**
* @throws NoSuchElementException {@inheritDoc}
*/
public K lastKey() {
return key(getLastEntry());
}
/**
* 将指定Map中的映射复制进来,会取代当前已存在的映射值
* @param map mappings to be stored in this map
* @throws ClassCastException if the class of a key or value in
* the specified map prevents it from being stored in this map
* @throws NullPointerException if the specified map is null or
* the specified map contains a null key and this map does not
* permit null keys
*/
public void putAll(Map<? extends K, ? extends V> map) {
int mapSize = map.size();
if (size==0 && mapSize!=0 && map instanceof SortedMap) {
Comparator<?> c = ((SortedMap<?,?>)map).comparator();
if (c == comparator || (c != null && c.equals(comparator))) {
++modCount;
try {
buildFromSorted(mapSize, map.entrySet().iterator(),
null, null);
} catch (java.io.IOException cannotHappen) {
} catch (ClassNotFoundException cannotHappen) {
}
return;
}
}
super.putAll(map);
}
/**
* 通过Key获取对应的结点
* @return this map's entry for the given key, or {@code null} if the map
* does not contain an entry for the key
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key is null
* and this map uses natural ordering, or its comparator
* does not permit null keys
*/
final Entry<K,V> getEntry(Object key) {
// 如果有比较器,返回getEntryUsingComparator(Object key)的结果
if (comparator != null)
return getEntryUsingComparator(key);
//查找的Key为null,抛出NullPointerException
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
//如果没有比较器,而是实现了 可比较接口
Comparable<? super K> k = (Comparable<? super K>) key;
//获取根节点
Entry<K,V> p = root;
//对树进行遍历查找结点
while (p != null) {
//把Key和当前节点的Key进行比较
int cmp = k.compareTo(p.key);
//Key小于当前结点的Key
if (cmp < 0)
//p“移动”到左节点上
p = p.left;
//key大于当前节点的Key
else if (cmp > 0)
//p移动到右结点上
p = p.right;
//key值相等则当前节点就是要找的结点
else
//返回找到的结点
return p;
}
//没有找到则返回null
return null;
}
/**
* 有比较器时获取指定关键字的Entry的方法
*/
final Entry<K,V> getEntryUsingComparator(Object key) {
@SuppressWarnings("unchecked")
K k = (K) key;
//获取比较器
Comparator<? super K> cpr = comparator;
//其实在调用此方法的get(Object key)中已经对比较器为null的情况进行判断,这里是防御性的判断
if (cpr != null) {
//获取根节点
Entry<K,V> p = root;
//遍历树
while (p != null) {
//获取Key和当前节点的Key的比较结果
int cmp = cpr.compare(k, p.key);
//查找的Key值较小
if (cmp < 0)
//p移动到左孩子
p = p.left;
//查找的Key值较大
else if (cmp > 0)
//p移动到右结点
p = p.right;
//key值相等
else
//返回找到的结点
return p;
}
}
//没找到Key值对应的结点,返回null
return null;
}
/**
* 获取指定关键字对应的Entry,如果没有就返回大于该关键字的最小关键字的Entry
* 如没有,返回null
*/
final Entry<K,V> getCeilingEntry(K key) {
Entry<K,V> p = root;
while (p != null) {
int cmp = compare(key, p.key);
//key比较小
if (cmp < 0) {
//进入左子树遍历
if (p.left != null)
p = p.left;
else
return p;
} else if (cmp > 0) { //key比较大
//进入右子树遍历
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;
}
} else
return p;
}
return null;
}
/**
* 获取指定关键字对应的Entry,如果没有对应的Entry,返回小于等于指定关键字的最大关键字的Entry,
* 如果不存在,返回null
*/
final Entry<K,V> getFloorEntry(K key) {
//获取根节点
Entry<K,V> p = root;
//不是空树,对树进行遍历
while (p != null) {
int cmp = compare(key, p.key);
//key较大
if (cmp > 0) {
//找到结点有右孩子,则继续向右孩子遍历
if (p.right != null)
p = p.right;
else //没有右孩子,那么p结点就是树中比传入key值小且最接近传入key的结点,就是要找的结点
return p;
} else if (cmp < 0) { //key值较小
//由左孩子向左孩子遍历
if (p.left != null) {
p = p.left;
} else { //没有左孩子,这个结点比key值大,
//返回内容是向上寻找到的根节点或比传入key值小的最后一个结点
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 //Key值相等
return p;
}
return null;
}
/**
* 获取指定关键字对应的Entry,如果没有对应的Entry,返回严格大于指定关键字的最小关键字的Entry,
* 如果没有则返回null
*/
final Entry<K,V> getHigherEntry(K key) {
//获取根节点
Entry<K,V> p = root;
//树不空,遍历树
while (p != null) {
int cmp = compare(key, p.key);
//key比较小
if (cmp < 0) {
//有左孩子,去左子树遍历
if (p.left != null)
p = p.left;
else //没有左孩子,那么p结点就是树中比传入key值大且最接近传入key的结点了
return p;
} else { //key比较大
//有右子树,向右子树遍历
if (p.right != null) {
p = p.right;
} else { //没有右孩子,这个结点比key小,
//返回内容是向上寻找到根节点或是比传入key值大的最后一个结点
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;
}
/**
* 返回严格小于指定关键字的的最大关键字的Entry
*/
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;
}
/**将指定关键字和指定值联系起来,如已存在,覆盖
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
*
* @return the previous value associated with {@code key}, or
* {@code null} if there was no mapping for {@code key}.
* (A {@code null} return can also indicate that the map
* previously associated {@code null} with {@code key}.)
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key is null
* and this map uses natural ordering, or its comparator
* does not permit null keys
*/
public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
compare(key, key); // 类型检查(可能为null)
//如果根节点为null,将传入的键值对构造成根节点(根节点没有父节点,所以传入的父节点为null)
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
//记录比较结果
int cmp;
Entry<K,V> parent;
// 分割比较器和可比较接口的处理
Comparator<? super K> cpr = comparator;
//有比较器的处理
if (cpr != null) {
//do while实现从根节点root开始移动寻找传入键值对需要插入的位置
do {
//记录将要被插入新的键值对的上一个结点(即新节点的父节点)
parent = t;
//使用比较器比较父节点和插入键值对的Key值的大小
cmp = cpr.compare(key, t.key);
//插入的Key较大,进入左子树
if (cmp < 0)
t = t.left;
//插入的Key较小,进入右子树
else if (cmp > 0)
t = t.right;
//key值相等,替换并返回t结点的value(put方法结束)
else
return t.setValue(value);
} while (t != null);
}
//没有比较器的处理
else {
//Key为null,抛出NullPointerException异常
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) key;
//与if中的do while类似,只是比较的方式不同
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);
}
//没有找到Key相同的结点才会有下面的操作
//根据传入的键值对和找到的“父节点”创建新节点
Entry<K,V> e = new Entry<>(key, value, parent);
//根据最后一次的判断结果确认新节点是“父节点”的左孩子还是右孩子
if (cmp < 0)
parent.left = e;
else
parent.right = e;
//对加入新节点的树进行调整
fixAfterInsertion(e);
//记录Size和modCount
size++;
modCount++;
//因为是插入新节点,所以返回是null
return null;
}
/**
* 删除指定关键字的映射
* @param key key for which mapping should be removed
* @return the previous value associated with {@code key}, or
* {@code null} if there was no mapping for {@code key}.
* (A {@code null} return can also indicate that the map
* previously associated {@code null} with {@code key}.)
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key is null
* and this map uses natural ordering, or its comparator
* does not permit null keys
*/
public V remove(Object key) {
//通过getEntry(Object key)获取结点
Entry<K,V> p = getEntry(key);
//指定Key的结点不存在,返回null
if (p == null)
return null;
//获取结点的value
V oldValue = p.value;
//删除结点
deleteEntry(p);
//返回结点的值
return oldValue;
}
/**
* 清空Map
*/
public void clear() {
modCount++;
size = 0;
root = null;
}
/**
* Returns a shallow copy of this {@code TreeMap} instance. (The keys and
* values themselves are not cloned.)
*
* @return a shallow copy of this map
*/
public Object clone() {
TreeMap<?,?> clone;
try {
clone = (TreeMap<?,?>) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
// Put clone into "virgin" state (except for comparator)
clone.root = null;
clone.size = 0;
clone.modCount = 0;
clone.entrySet = null;
clone.navigableKeySet = null;
clone.descendingMap = null;
// Initialize clone with our mappings
try {
clone.buildFromSorted(size, entrySet().iterator(), null, null);
} catch (java.io.IOException cannotHappen) {
} catch (ClassNotFoundException cannotHappen) {
}
return clone;
}
// NavigableMap接口的函数
/**
* @since 1.6
*/
public Map.Entry<K,V> firstEntry() {
return exportEntry(getFirstEntry());
}
/**
* @since 1.6
*/
public Map.Entry<K,V> lastEntry() {
return exportEntry(getLastEntry());
}
/**
* 获取并移除最小结点
* @since 1.6
*/
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;
}
/**
* 获取并移除最大结点
* @since 1.6
*/
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;
}
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if the specified key is null
* and this map uses natural ordering, or its comparator
* does not permit null keys
* @since 1.6
*/
public Map.Entry<K,V> lowerEntry(K key) {
return exportEntry(getLowerEntry(key));
}
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if the specified key is null
* and this map uses natural ordering, or its comparator
* does not permit null keys
* @since 1.6
*/
public K lowerKey(K key) {
return keyOrNull(getLowerEntry(key));
}
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if the specified key is null
* and this map uses natural ordering, or its comparator
* does not permit null keys
* @since 1.6
*/
public Map.Entry<K,V> floorEntry(K key) {
return exportEntry(getFloorEntry(key));
}
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if the specified key is null
* and this map uses natural ordering, or its comparator
* does not permit null keys
* @since 1.6
*/
public K floorKey(K key) {
return keyOrNull(getFloorEntry(key));
}
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if the specified key is null
* and this map uses natural ordering, or its comparator
* does not permit null keys
* @since 1.6
*/
public Map.Entry<K,V> ceilingEntry(K key) {
return exportEntry(getCeilingEntry(key));
}
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if the specified key is null
* and this map uses natural ordering, or its comparator
* does not permit null keys
* @since 1.6
*/
public K ceilingKey(K key) {
return keyOrNull(getCeilingEntry(key));
}
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if the specified key is null
* and this map uses natural ordering, or its comparator
* does not permit null keys
* @since 1.6
*/
public Map.Entry<K,V> higherEntry(K key) {
return exportEntry(getHigherEntry(key));
}
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if the specified key is null
* and this map uses natural ordering, or its comparator
* does not permit null keys
* @since 1.6
*/
public K higherKey(K key) {
return keyOrNull(getHigherEntry(key));
}
// Views
/**
* Fields initialized to contain an instance of the entry set view
* the first time this view is requested. Views are stateless, so
* there's no reason to create more than one.
*/
private transient EntrySet entrySet = null;
private transient KeySet<K> navigableKeySet = null;
private transient NavigableMap<K,V> descendingMap = null;
/**
* Returns a {@link Set} view of the keys contained in this map.
*
* <p>The set's iterator returns the keys in ascending order.
* The set's spliterator is
* <em><a href="Spliterator.html#binding">late-binding</a></em>,
* <em>fail-fast</em>, and additionally reports {@link Spliterator#SORTED}
* and {@link Spliterator#ORDERED} with an encounter order that is ascending
* key order. The spliterator's comparator (see
* {@link java.util.Spliterator#getComparator()}) is {@code null} if
* the tree map's comparator (see {@link #comparator()}) is {@code null}.
* Otherwise, the spliterator's comparator is the same as or imposes the
* same total ordering as the tree map's comparator.
*
* <p>The set is backed by the map, so changes to the map are
* reflected in the set, and vice-versa. If the map is modified
* while an iteration over the set is in progress (except through
* the iterator's own {@code remove} operation), the results of
* the iteration are undefined. The set supports element removal,
* which removes the corresponding mapping from the map, via the
* {@code Iterator.remove}, {@code Set.remove},
* {@code removeAll}, {@code retainAll}, and {@code clear}
* operations. It does not support the {@code add} or {@code addAll}
* operations.
*/
public Set<K> keySet() {
return navigableKeySet();
}
public NavigableSet<