首页 > 其他分享 >使用HashMap的containsKey查找键,时间复杂度为什么是O(1)?

使用HashMap的containsKey查找键,时间复杂度为什么是O(1)?

时间:2023-03-05 10:07:23浏览次数:32  
标签:null hash HashMap 复杂度 哈希 查找 key containsKey 节点


[1] 总览

  在Java中,"containsKey"是Map接口中定义的一个方法,用于判断给定的键(key)是否存在于Map中。Map是Java中的一种数据结构,用于存储键值对(key-value pairs),其中每个键都是唯一的。

  "containsKey"方法接受一个键作为参数,如果Map中存在该键,则返回true,否则返回false。

  "containsKey"方法的时间复杂度为O(1),即常数时间,因为它使用了哈希表(hash table)来实现。哈希表是一种高效的数据结构,可以在常数时间内执行插入、查找和删除操作。因此,"containsKey"方法通常用于快速检查Map中是否包含某个键,而不必遍历整个Map。

[2] 为什么hashtable可以在常数时间内执行插入、查找和删除操作?

  哈希表(hash table)可以在常数时间内执行插入、查找和删除操作,是因为它使用了哈希函数(hash function)来将键映射到索引上。

  具体来说,哈希函数将键映射到哈希表中的一个桶(bucket)上,每个桶存储了一个链表或者红黑树等数据结构,用于存储具有相同哈希值的键值对。

  在哈希表中,插入一个键值对的时间复杂度是O(1),因为只需要计算出键的哈希值,然后将它插入到对应的桶中。

  同样,查找和删除操作的时间复杂度也是O(1),因为可以根据键的哈希值直接定位到对应的桶,然后在桶中查找或删除该键值对。

  然而,如果哈希函数的设计不合理,可能会导致哈希表中的冲突(collision),即不同的键被映射到同一个桶中。这种情况下,需要使用链表或红黑树等数据结构来解决冲突。在最坏情况下,所有键都被映射到同一个桶中,导致链表或红黑树的长度变为N,此时插入、查找和删除的时间复杂度将变为O(N)。为了避免这种情况,需要使用一种好的哈希函数,使得键被平均分布到各个桶中,从而使得插入、查找和删除的平均时间复杂度保持为O(1)。

[3] HashMap的containsKey方法底层详解

/**
* 检查是否包含key
* 如果key有对应的节点对象,则返回ture,不关心节点对象的值是否为空
*/
public boolean containsKey(Object key) {
// 调用getNode方法来获取键值对,如果没有找到返回false,找到了就返回ture
return getNode(hash(key), key) != null; //真正的查找过程都是通过getNode方法实现的
}

/**
* 该方法是Map.get方法的具体实现
* 接收两个参数
* @param hash key的hash值,根据hash值在节点数组中寻址,该hash值是通过hash(key)得到的,可参见:hash方法解析
* @param key key对象,当存在hash碰撞时,要逐个比对是否相等
* @return 查找到则返回键值对节点对象,否则返回null
*/
final Node<K,V> getNode(int hash, Object key) {
Node<K,V>[] tab; Node<K,V> first, e; int n; K k; // 声明节点数组对象、链表的第一个节点对象、循环遍历时的当前节点对象、数组长度、节点的键对象
// 节点数组赋值、数组长度赋值、通过位运算得到求模结果确定链表的首节点
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) {
if (first.hash == hash && // 首先比对首节点,如果首节点的hash值和key的hash值相同 并且 首节点的键对象和key相同(地址相同或equals相等),则返回该节点
((k = first.key) == key || (key != null && key.equals(k))))
return first; // 返回首节点

// 如果首节点比对不相同、那么看看是否存在下一个节点,如果存在的话,可以继续比对,如果不存在就意味着key没有匹配的键值对
if ((e = first.next) != null) {
// 如果存在下一个节点 e,那么先看看这个首节点是否是个树节点
if (first instanceof TreeNode)
// 如果是首节点是树节点,那么遍历树来查找
return ((TreeNode<K,V>)first).getTreeNode(hash, key);

// 如果首节点不是树节点,就说明还是个普通的链表,那么逐个遍历比对即可
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) // 比对时还是先看hash值是否相同、再看地址或equals
return e; // 如果当前节点e的键对象和key相同,那么返回e
} while ((e = e.next) != null); // 看看是否还有下一个节点,如果有,继续下一轮比对,否则跳出循环
}
}
return null; // 在比对完了应该比对的树节点 或者全部的链表节点 都没能匹配到key,那么就返回null
}


标签:null,hash,HashMap,复杂度,哈希,查找,key,containsKey,节点
From: https://blog.51cto.com/u_15942590/6101098

相关文章

  • java 中HashMap集合框架的应用
    NIO2007某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*109)。已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序......
  • 理论:第一章:HashMap底层实现原理,红黑树,B+树,B树的结构原理,volatile关键字,CAS(比较与交换)
    首先HashMap是Map的一个实现类,而Map存储形式是键值对(key,value)的。可以看成是一个一个的Entry。Entry所存放的位置是由key来决定的。Map中的key是无序的且不可重复的,所......
  • java HashMap 源码
    jdk1.7和1.8区别比较大,主要是数据结构上的区别从而put()get()等方法也会有相应变化jdk1.7数据结构为数组(buckets)+单向链表(entries)hash冲突时......
  • HashMap
    数据结构:​HashMap在底层数据结构上采用了数组+链表+红黑树,通过散列映射来存储键值对数据扩容情况:​默认的负载因子是0.75,如果数组中已经存储的元素个数大于数组长度的7......
  • hashmap深入理解
    1.Map:地图* 1.概念:Map:就是用来装键值对集合的容器* 2.作用:* 解决了需要成对出现的这种关系结构* 键(key): 本质就是一个数据 值(value): 本质也是......
  • Java容器类List、ArrayList、Vector及map、HashTable、HashMap
    ArrayList和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素,但是插入数据要设计到数组元素移动等内存操作,所以索引......
  • 衡量算法的性能-时空复杂度分析
    算法即存在输入输出,由有限步骤结束的程序.因此,显而易见,算法并不是指一个单一的标准答案,而是一切能够完成要求的程序都可以称之为算法.但是算法之间根据性能的不同存......
  • 时间复杂度精讲
    1、什么是时间复杂度和空间复杂度1.1算法效率算法效率分析分为两种:第一种是时间效率,第二种是空间效率。时间效率被称为时间复杂度,二空间效率被称为空间复杂度。时间复杂度主......
  • 数据结构与算法【基础版】:3.1算法的时间复杂度和空间复杂度的概述
    如何衡量一个算法的优劣?一、事后统计的方法让算法先在电脑上跑一下,整一个计时器来算一下执行一次运行了多长时间。缺点:同一台电脑,在运行同一个程序,执行同一个任务的时候,占......
  • jdk8中的hashmap
    传送门:jdk7中的HashMap源码解读jdk8中的HashMap与jdk7相比最大的不同就是引入了红黑树,当链表中的元素大于8个时就会把链表转成红黑树,下面来简单分析下8中的HashMap源码。......