TreeMap采用了红黑树的数据结构。
一、红黑树
红黑树是一个二叉搜索树,它在每个节点上增加了一个存储位来表示节点颜色,可以是RED或BLACK。红黑树的本质还是二叉树。由二叉树进化为2-3树或者是2-3-4树,然后再进化为红黑树,接下来将《算法导论》和《算法(第四版)》中的红黑树进行对比。
《算法导论》中规则:
(1)、每个节点都只能是红色或者黑色;
(2)、根节点是黑色;
(3)、每个叶节点(NIL节点,空节点)是黑色的;
(4)、如果一个结点是红的,则它两个子节点都是黑的。也就是说在一条路径上不能出现相邻的两个红色结点;
(5)、从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
《算法(第四版)》中的规则:
将3-结点表示为一条左斜的红色链接(两2-结点其中之一是另一个的左子结点)相连的两个2-结点。黑链接则为普通链接。
(1)、红连接均为左链接;
(2)、没有任何一个结点同时和两条红链接相连;
(3)、该树是完美黑色平衡的,即任意空链接到根节点的路径上的黑链接数量相同。
在TreeMap中定义的数据结点及一些基本操作:
static final class Entry<K,V> implements Map.Entry<K,V> {
K key;
V value;
Entry<K,V> left;
Entry<K,V> right;
Entry<K,V> parent;
boolean color = BLACK;
//使用给定的键,值和父结点,以及null子链接和BLACK颜色创建一个新单元格。
Entry(K key, V value, Entry<K,V> parent) {
this.key = key;
this.value = value;
this.parent = parent;
}
//返回key
public K getKey() {
return key;
}
//返回与该key关联的value
public V getValue() {
return value;
}
//将当前与key相关联的value替换为给定value
public V setValue(V value) {
V oldValue = this.value;
this.value = value;
return oldValue;
}
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
return valEquals(key,e.getKey()) && valEquals(value,e.getValue());
}
public int hashCode() {
int keyHash = (key==null ? 0 : key.hashCode());
int valueHash = (value==null ? 0 : value.hashCode());
return keyHash ^ valueHash;
}
public String toString() {
return key + "=" + value;
}
}
//返回TreeMap中的第一个结点(根据TreeMap的key排序功能)。 如果TreeMap为空,则返回null。
final Entry<K,V> getFirstEntry() {
Entry<K,V> p = root;
//通过一直查找左结点找到第一个结点
if (p != null)
while (p.left != null)
p = p.left;
return p;
}
//返回TreeMap中的最后一个结点(根据TreeMap的key排序功能)。 如果TreeMap为空,则返回null。
final Entry<K,V> getLastEntry() {
Entry<K,V> p = root;
//通过一直查找右结点找到最后一个结点
if (p != null)
while (p.right != null)
p = p.right;
return p;
}
//返回指定的结点的后继结点,如果没有,则返回null。
static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) {
//如果指定结点为null,则返回null
if (t == null)
return null;
//如果指定结点的右结点不为null,则查找右子树的第一个结点
else if (t.right != null) {
Entry<K,V> p = t.right;
while (p.left != null)
p = p.left;
return p;
} else {
//如果右结点为null
Entry<K,V> p = t.parent;
Entry<K,V> ch = t;
//如果指定结点为父结点的右结点,则一直查找父结点,
//向上查找,直到出现某结点为父结点的左结点为止,此时返回此结点的父结点
//否则一直查找向上查找,直到返回null
while (p != null && ch == p.right) {
ch = p;
p = p.parent;
}
return p;
}
}
//返回指定Entry的前续结点,如果没有,则返回null。
static <K,V> Entry<K,V> predecessor(Entry<K,V> t) {
//如果指定结点为null,则返回null
if (t == null)
return null;
//如果指定结点的左结点不为null,则查找其左子树的左后一个结点
else if (t.left != null) {
Entry<K,V> p = t.left;
while (p.right != null)
p = p.right;
return p;
} else {
//如果指定结点的左结点为null
Entry<K,V> p = t.parent;
Entry<K,V> ch = t;
//如果指定结点为父结点的左结点,则一直查找父结点,
//向上查找,直到出现某结点为父结点的右结点为止,此时返回此结点的父结点
//否则一直查找向上查找,直到返回null
while (p != null && ch == p.left) {
ch = p;
p = p.parent;
}
return p;
}
}
二、TreeMap中红黑树的插入和删除操作
2.1 树结点的旋转操作
左旋转代码:
//左旋转
private void rotateLeft(Entry<K,V> p) {
if (p != null) {
Entry<K,V> r = p.right;
//旋转后,将p与p.right.left相关联
p.right = r.left;
if (r.left != null)
r.left.parent = p;
//r(p.right)代替p的位置
r.parent = p.parent;
if (p.parent == null)
root = r;
else if (p.parent.left == p)
p.parent.left = r;
else
p.parent.right = r;
//p与r(原来的p.right)重新关联
r.left = p;
p.parent = r;
}
}
右旋转代码:
//右旋转
private void rotateRight(Entry<K,V> p) {
if (p != null) {
Entry<K,V> l = p.left;
//旋转后,将p与p.left.right相关联
p.left = l.right;
if (l.right != null) l.right.parent = p;
//l(p.left)替换p的位置
l.parent = p.parent;
if (p.parent == null)
root = l;
else if (p.parent.right == p)
p.parent.right = l;
else p.parent.left = l;
//p与l(原来的p.left)重新关联
l.right = p;
p.parent = l;
}
}
2.2 结点的插入操作
2.2.1 插入操作的源代码
//将指定的value与此映射中的指定key相关联。 如果map先前包含了该key的映射,则替换旧值。
public V put(K key, V value) {
//定义t为根结点
Entry<K,V> t = root;
//如果t表示一个空树
if (t == null) {
compare(key, key); //类型(可能为null)检查
//将该结点设置为根结点root
root = new Entry<>(key, value, null);
//将容器的大小+1
size = 1;
modCount++;
return null;
}
int cmp;
//定义父结点
Entry<K,V> parent;
//拆分比较器和可比路径
//指定排序算法
Comparator<? super K> cpr = comparator;
//如果cpr不为空,使用指定的排序算法
if (cpr != null) {
do {
//经过循环之后,t往下移动为要插入结点的位置,parent为指向上一次t的位置,为t的父结点
parent = t;
//比较新增结点的key值与当前结点t的key值大小
cmp = cpr.compare(key, t.key);
//从上往下进行查找新增结点的位置,直到将t是叶结点
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
//如果cpr为空,只用默认的排序算法,分析同上
else {
//如果key为空,报错
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);
}
//创建新结点,并将parent作为父结点
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;
}
2.2.2 插入后的树结构调整
原理:分为三种情况
情况1:如果x的叔结点为RED
情况2:叔结点为黑色,x为右孩子
情况3:叔结点为黑色,x为左孩子
代码分析:
//新增结点之后的调整修复操作
private void fixAfterInsertion(Entry<K,V> x) {
x.color = RED;
//循环,直到x不是根结点,并且父结点不为红色
//父结点为红色违背性质四
while (x != null && x != root && x.parent.color == RED) {
//x的父结点为左结点
if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
//定义y为x的右叔结点
Entry<K,V> y = rightOf(parentOf(parentOf(x)));
//如果x的叔结点为RED:情况一
if (colorOf(y) == RED) {
//将x的父结点设置为黑色
setColor(parentOf(x), BLACK);
//将x的叔结点设置为黑色
setColor(y, BLACK);
//将x的父结点的父结点设置为红色
setColor(parentOf(parentOf(x)), RED);
//将x指向自己的父结点的父结点
x = parentOf(parentOf(x));
} else { //x的叔结点y为黑色,情况2和情况3
//情况2:叔结点为黑色,x为右孩子,则以x的父节点为中心进行左旋转,将情况2转变成情况3
if (x == rightOf(parentOf(x))) {
//将x指向自己的父结点
x = parentOf(x);
//左旋转
rotateLeft(x);
}
//情况3;叔结点为黑色,x为左孩子
//如果x为左结点,则将x的父结点颜色设置为黑色
setColor(parentOf(x), BLACK);
//将x的父结点的父结点的颜色设置为红色
setColor(parentOf(parentOf(x)), RED);
//以x的父结点的父结点为中心进行右旋转
rotateRight(parentOf(parentOf(x)));
}
} else {
//定义y为x的左叔结点,分析同上
Entry<K,V> y = leftOf(parentOf(parentOf(x)));
if (colorOf(y) == RED) {
setColor(parentOf(x), BLACK);
setColor(y, BLACK);
setColor(parentOf(parentOf(x)), RED);
x = parentOf(parentOf(x));
} else {
if (x == leftOf(parentOf(x))) {
x = parentOf(x);
rotateRight(x);
}
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
rotateLeft(parentOf(parentOf(x)));
}
}
}
root.color = BLACK;
}
2.3 删除结点操作
2.3.1 删除操作源码
//删除结点p
private void deleteEntry(Entry<K,V> p) {
modCount++;
size--;
// 如果删除指定结点p的左子树和右子树不为空(或者p有两个子结点),则将p替换为该后继结点
if (p.left != null && p.right != null) {
Entry<K,V> s = successor(p);
p.key = s.key;
p.value = s.value;
p = s;
}
//开始修复替换结点(如果存在)。
Entry<K,V> replacement = (p.left != null ? p.left : p.right);
if (replacement != null) {
//将替换结点连接到y的父结点
replacement.parent = p.parent;
//如果p的父结点为null,即p为根结点,则替换结点这是为根结点
if (p.parent == null)
root = replacement;
else if (p == p.parent.left) //如果p为左子结点,则将y父结点的左结点连接到替换结点
p.parent.left = replacement;
else //如果p为右子结点,则将y父结点的右结点连接到替换结点
p.parent.right = replacement;
//取消p的链接,交给GC回收。
p.left = p.right = p.parent = null;
//如果p的结点颜色为黑色,对红黑树进行调整
if (p.color == BLACK)
fixAfterDeletion(replacement);
} else if (p.parent == null) { //此时p为唯一结点
root = null;
} else { //p没有子结点,即p为叶结点
if (p.color == BLACK) //如果P结点的颜色为黑色,对红黑树进行调整
fixAfterDeletion(p);
//将取消p与父结点的连接
if (p.parent != null) {
if (p == p.parent.left)
p.parent.left = null;
else if (p == p.parent.right)
p.parent.right = null;
p.parent = null;
}
}
}
2.3.2 删除结点后的树结构的调整
原理:分为三种情况
情况1:x的兄弟结点sib为红色
情况2:指定结点x的兄弟结点sib是黑色结点,而且sib的两个子结点都是黑色结点
情况3:指定结点x的兄弟结点sib是黑色结点,sib的右结点为黑色结点,左结点为红色结点
情况4:指定结点x的兄弟结点sib为黑色结点,sib的右结点为红色结点
调整操作的源代码:
// 删除完结点后,就要根据情况来对红黑树进行调整
private void fixAfterDeletion(Entry<K,V> x) {
//指定结点不是根结点,并且结点颜色为黑色
while (x != root && colorOf(x) == BLACK) {
//如果x为左子结点
if (x == leftOf(parentOf(x))) {
//定义sib为x的兄弟结点
Entry<K,V> sib = rightOf(parentOf(x));
//x的兄弟结点sib为红色:情况1.
if (colorOf(sib) == RED) {
//将指定结点x的兄弟结点sib的颜色设置为黑色
setColor(sib, BLACK);
//将指定结点x的的父结点的颜色设置为红色
setColor(parentOf(x), RED);
//以指定结点x的父结点为中心,向左进行旋转
rotateLeft(parentOf(x));
//此时指定结点x的兄弟结点sib改变,重置兄弟结点
sib = rightOf(parentOf(x));
}
//兄弟结点sib的颜色为黑色,情况2、情况3、情况4
//情况2:指定结点x的兄弟结点sib是黑色结点,而且sib的两个子结点都是黑色结点
if (colorOf(leftOf(sib)) == BLACK &&
colorOf(rightOf(sib)) == BLACK) {
//将sib设置为红色结点
setColor(sib, RED);
//将x指向自己的父结点
x = parentOf(x);
} else {
//情况3:指定结点x的兄弟结点sib是黑色结点,sib的右结点为黑色结点,左结点为红色结点
//将情况3转换为情况4
if (colorOf(rightOf(sib)) == BLACK) {
//将sib的左结点设置为黑色结点
setColor(leftOf(sib), BLACK);
//将sib设置为红色
setColor(sib, RED);
//以sib为中心,向右进行旋转
rotateRight(sib);
//此时指定结点x的兄弟结点sib改变,重置兄弟结点
sib = rightOf(parentOf(x));
}
//情况4:指定结点x的兄弟结点sib为黑色结点,sib的右结点为红色结点
//将sib的结点颜色设置为x的父结点颜色
setColor(sib, colorOf(parentOf(x)));
//将x父结点的颜色设置为黑色
setColor(parentOf(x), BLACK);
//将sib的右结点的颜色设置为黑色
setColor(rightOf(sib), BLACK);
//以x的父结点为中心,向左尽心旋转
rotateLeft(parentOf(x));
x = root;
}
} else { //过程与之前一样,只是分为作为左右结点进行分析
Entry<K,V> sib = leftOf(parentOf(x));
if (colorOf(sib) == RED) {
setColor(sib, BLACK);
setColor(parentOf(x), RED);
rotateRight(parentOf(x));
sib = leftOf(parentOf(x));
}
if (colorOf(rightOf(sib)) == BLACK &&
colorOf(leftOf(sib)) == BLACK) {
setColor(sib, RED);
x = parentOf(x);
} else {
if (colorOf(leftOf(sib)) == BLACK) {
setColor(rightOf(sib), BLACK);
setColor(sib, RED);
rotateLeft(sib);
sib = leftOf(parentOf(x));
}
setColor(sib, colorOf(parentOf(x)));
setColor(parentOf(x), BLACK);
setColor(leftOf(sib), BLACK);
rotateRight(parentOf(x));
x = root;
}
}
}
setColor(x, BLACK);
}
三、TreeMap实现的部分方法
//使用其键的自然排序构造一个新的、空的树形图。 插入map的所有key都必须实现Comparable。此外,
//所有这些密钥必须相互比较k1.compareTo(k2)不得为任何k1和k2引发ClassCastException在map上。
//如果用户试图将一个key放入违反该约束的地图map(例如,用户尝试将一个字符串键放入一个键为整数的map中),
//put(Object key,Object value)调用将抛出ClassCastException。
public TreeMap() {
comparator = null;
}
//构造一个新的、空的树图,根据给定的比较器排序。
//插入到地图中的所有键必须由给定的比较器相互比较comparator.compare(k1,k2)
//不得为任何k1和k2抛出ClassCastException。
//如果用户尝试将一个key放入违反此约束的map中,则put(Object key,Object value)调用将抛出ClassCastException
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
//构造一个新的树图,其中包含与给定地图相同的映射,根据其key的自然排序进行排序。
//插入新地图的所有键必须实现Comparable接口。 此外,所有这些key必须相互比较k1.compareTo(k2)
//不得在map上为k1和k2任何一个key引发ClassCastException。 此方法运行在n*log(n)时间。
public TreeMap(Map<? extends K, ? extends V> m) {
comparator = null;
putAll(m);
}
//构造一个包含相同映射并使用与指定排序映射相同顺序的新树映射。该方法运行在线性时间。
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) {
}
}
// 查询操作
//返回此映射中key-value映射的数量。
public int size() {
return size;
}
//如果此映射包含指定key的映射,则返回true
public boolean containsKey(Object key) {
return getEntry(key) != null;
}
//如果此映射将一个或多个键映射到指定的值,则返回true。
public boolean containsValue(Object value) {
for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e))
if (valEquals(value, e.value))
return true;
return false;
}
//返回指定key映射到的值,如果此映射不包含该key的映射,则返回null
public V get(Object key) {
Entry<K,V> p = getEntry(key);
return (p==null ? null : p.value);
}
public Comparator<? super K> comparator() {
return comparator;
}
public K firstKey() {
return key(getFirstEntry());
}
public K lastKey() {
return key(getLastEntry());
}
//将指定map的所有映射复制到此map。
public void putAll(Map<? extends K, ? extends V> map) {
int mapSize = map.size();
if (size==0 && mapSize!=0 && map instanceof SortedMap) {
// 如果TreeMap和map的比较器相等;则将map的元素全部拷贝到TreeMap中,然后返回
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的条目,如果映射不包含该key的条目,则返回null
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;
}
//使用比较器的getEntry版本。从getEntry中分离来执行性能。
//(这对于大多数方法来说都不值得,因为比较器的性能不太依赖,但在这里是值得的。)
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;
}
//获取与指定key对应的条目;
//如果不存在这样的条目,则返回大于指定key的最小key的条目;
//如果不存在这样的条目(即,Tree中最大的key小于指定的key),返回 null
final Entry<K,V> getCeilingEntry(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 (cmp > 0) {
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;
}
//获取与指定key对应的条目;
//如果不存在这样的条目,则返回小于指定key的最大key的条目;
//如果没有这样的条目,返回null
final Entry<K,V> getFloorEntry(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 (cmp < 0) {
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;
}
} else
return p;
}
return null;
}
//获取大于指定key的最小key的条目;
//如果不存在这样的条目,则返回大于指定key的最小key的条目;
//如果没有这样的条目返回null
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;
}
//返回小于指定key的最大key的条目;
//如果不存在这样的条目(即,树中的最小key大于指定的key),返回null
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;
}
//从此TreeMap中删除此key的映射(如果存在)。
public V remove(Object key) {
Entry<K,V> p = getEntry(key);
if (p == null)
return null;
V oldValue = p.value;
deleteEntry(p);
return oldValue;
}
//从此map中删除所有的映射。此调用返回后,map将为空。
public void clear() {
modCount++;
size = 0;
root = null;
}
//返回此TreeMap实例的浅层副本。(key和value本身不被克隆。)
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 API methods
//返回与此映射中的最小键相关联的键值映射,如果映射为空,则返回null。
public Map.Entry<K,V> firstEntry() {
return exportEntry(getFirstEntry());
}
//返回与该地图中最大关键字关联的键值映射,如果地图为空,则返回null。
public Map.Entry<K,V> lastEntry() {
return exportEntry(getLastEntry());
}
//删除并返回与该映射中的最小密钥相关联的键值映射,如果映射为空,则返回null。
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;
}
//删除并返回与该地图中最大键相关联的键值映射,如果地图为空,则返回null。
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;
}
//返回与最大密钥相关联的密钥值映射严格小于给定密钥,如果没有这样的密钥,则返回null。
public Map.Entry<K,V> lowerEntry(K key) {
return exportEntry(getLowerEntry(key));
}
//返回严格小于给定键的最大键,如果没有这样的键返回null。
public K lowerKey(K key) {
return keyOrNull(getLowerEntry(key));
}
//返回与小于或等于给定键的最大键相关联的键值映射,如果没有此键,则返回null。
public Map.Entry<K,V> floorEntry(K key) {
return exportEntry(getFloorEntry(key));
}
//返回小于或等于给定键的最大键,如果没有此键,则返回null。
public K floorKey(K key) {
return keyOrNull(getFloorEntry(key));
}
//返回与最小键相关联的键值映射大于或等于给定键,如果没有此键,则返回null。
public Map.Entry<K,V> ceilingEntry(K key) {
return exportEntry(getCeilingEntry(key));
}
//返回大于或等于给定键的最小键,如果没有此键,则返回null。
public K ceilingKey(K key) {
return keyOrNull(getCeilingEntry(key));
}
//返回与最小键相关联的键值映射严格大于给定的键,如果没有这样的键,则返回null。
public Map.Entry<K,V> higherEntry(K key) {
return exportEntry(getHigherEntry(key));
}
//Returns the least key strictly greater than the given key, or null if there is no such key.
public K higherKey(K key) {
return keyOrNull(getHigherEntry(key));
}
//返回此映射中包含的映射的反向排序视图。
public NavigableMap<K, V> descendingMap() {
NavigableMap<K, V> km = descendingMap;
return (km != null) ? km :
(descendingMap = new DescendingSubMap<>(this,
true, null, true,
true, null, true));
}
//返回该地图的部分的视图,其关键范围从fromKey到kyo。
public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
K toKey, boolean toInclusive) {
return new AscendingSubMap<>(this,
false, fromKey, fromInclusive,
false, toKey, toInclusive);
}
//返回该地图的部分的视图,其键值小于(或等于,如果包含值为true)toKey。
public NavigableMap<K,V> headMap(K toKey, boolean inclusive) {
return new AscendingSubMap<>(this,
true, null, true,
false, toKey, inclusive);
}
//返回这个地图的部分的视图,其键大于(或等于,如果包含值为true)fromKey。
public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) {
return new AscendingSubMap<>(this,
false, fromKey, inclusive,
true, null, true);
}
//返回该地图部分的视图,其关键范围从fromKey(包括)到toKey(独占)。
public SortedMap<K,V> subMap(K fromKey, K toKey) {
return subMap(fromKey, true, toKey, false);
}
//返回该地图的部分密钥严格小于toKey的视图。
public SortedMap<K,V> headMap(K toKey) {
return headMap(toKey, false);
}
//返回此地图部分的视图,其键大于或等于fromKey。
public SortedMap<K,V> tailMap(K fromKey) {
return tailMap(fromKey, true);
}
//仅当当前映射到指定的值时,才能替换指定键的条目。
public boolean replace(K key, V oldValue, V newValue) {
Entry<K,V> p = getEntry(key);
if (p!=null && Objects.equals(oldValue, p.value)) {
p.value = newValue;
return true;
}
return false;
}
//只有当目标映射到某个值时,才能替换指定键的条目。
public V replace(K key, V value) {
Entry<K,V> p = getEntry(key);
if (p!=null) {
V oldValue = p.value;
p.value = value;
return oldValue;
}
return null;
}
//对此映射中的每个条目执行给定的操作,直到所有条目都被处理或操作引发异常。
public void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action);
int expectedModCount = modCount;
for (Entry<K, V> e = getFirstEntry(); e != null; e = successor(e)) {
action.accept(e.key, e.value);
if (expectedModCount != modCount) {
throw new ConcurrentModificationException();
}
}
}
//将每个条目的值替换为对该条目调用给定函数的结果,直到所有条目都被处理或该函数抛出异常。
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
Objects.requireNonNull(function);
int expectedModCount = modCount;
for (Entry<K, V> e = getFirstEntry(); e != null; e = successor(e)) {
e.value = function.apply(e.key, e.value);
if (expectedModCount != modCount) {
throw new ConcurrentModificationException();
}
}
}