containsValue 方法是 Java HashMap 类中的一个方法,用于检查 HashMap 是否包含特定的值。该方法遍历 HashMap 中的所有条目,检查是否有任何一个条目的值等于给定的值。 containsValue()源码如下:
public boolean containsValue(Object value) {
Node<K,V>[] tab; V v;
if ((tab = table) != null && size > 0) {
for (int i = 0; i < tab.length; ++i) {
for (Node<K,V> e = tab[i]; e != null; e = e.next) {
if ((v = e.value) == value ||
(value != null && value.equals(v)))
return true;
}
}
}
return false;
}
学习Map的时候毫无疑问containsKey()的原理一定是用key的hashcode定位,所以时间复杂度为O(1),但对于containsValue()并没有一个清晰的认识,仔细读了一下它的源码,觉得对hashmap的底层认识很有帮助。
public boolean containsValue(Object value) {
// 获取哈希表的数组引用和要查找的值
Node<K,V>[] tab; V v;
// 如果哈希表不为空且包含至少一个元素
if ((tab = table) != null && size > 0) {
// 遍历哈希表数组中的每个桶(bucket)
for (int i = 0; i < tab.length; ++i) {
// 遍历当前桶中的每个节点(链表或红黑树)
for (Node<K,V> e = tab[i]; e != null; e = e.next) {
// 获取当前节点的值
if ((v = e.value) == value ||
// 如果值不为null,则使用equals方法比较值
(value != null && value.equals(v)))
// 如果找到了匹配的值,返回true
return true;
}
}
}
// 如果没有找到匹配的值,返回false
return false;
}
在这个方法中,tab
是 HashMap
内部用于存储键值对的数组,value
是我们要查找的值。该方法首先检查 tab
是否不为 null
且 HashMap
的大小(size
)大于 0,以确保哈希表已经被初始化且包含至少一个元素。
然后,它遍历哈希表的每个桶(tab[i]
),在每个桶中遍历链表或红黑树(取决于 HashMap
的实现和树化的阈值)。对于每个节点,它检查节点的值是否与给定的 value
相等。这里有两种情况:
- 如果节点的值和给定的
value
是同一个对象的引用(即它们在内存中指向同一个位置),则直接使用==
运算符进行比较。 - 如果节点的值和给定的
value
不是同一个对象的引用,但它们是逻辑上相等的(即它们的内容相同),则使用equals
方法进行比较。
如果找到了任何匹配的值,方法会立即返回 true
。如果遍历了所有的桶和节点都没有找到匹配的值,方法最后会返回 false
。
这种方法的时间复杂度在最坏情况下是 O(n),其中 n 是 HashMap
中的条目数,因为需要遍历所有的条目来查找给定的值。在实际应用中,由于哈希表的分散性质,通常不需要遍历所有的条目就能找到值,所以平均时间复杂度通常要低于 O(n)。