热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

hashmap查询时间复杂度为O(1)的原因是什么

本篇内容介绍了“hashmap查询时间复杂度为O(1)的原因是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带

本篇内容介绍了“hashmap查询时间复杂度为O(1)的原因是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

hashmap为什么查询时间复杂度为O(1)

Hashmap是java里面一种类字典式数据结构类,能达到O(1)级别的查询复杂度,那么到底是什么保证了这一特性呢,这个就要从hashmap的底层存储结构说起

下来看一张图:

hashmap查询时间复杂度为O(1)的原因是什么

上面就是hashmap的底层存储示意图,要想查看一个键值对应的值,首先根据该键值的hash值找到该键的hash桶位置,即是tab[2]还是tab[1]等,计算某个键对应的哈希桶位置很简单,就是

int pos = (n - 1) & hash,也就是hash%n,因为位运算效率高所以在hashmap实现时使用的是位运算这种方式,需要注意的是哈希桶的数量必须是2^n,所以hashmap一旦扩容必定是哈希桶数量翻番。

通过上面的描述,我们可以知道,根据键值找到哈希桶的位置时间复杂度为O(1),使用的就是数组的高效查询。但是仅仅有这个是无法满足整个hashmap查询时间复杂度为O(1)的。hashmap在处理哈希冲突的方式如上图所示的拉链法,在冲突数据没有达到8个以前该哈希桶内部存储使用的是链表的方式,当某个哈希桶的数据超过8个的情况下,

有下面两种处理方式:

1、哈希桶的数量是没有超过64个,那么此时哈希桶数量double,然后数据迁移

2、哈希桶的数量超过了64个,将该哈希桶内部数据进行红黑树化处理

所以我们可以看到如果所有哈希桶内部数据都是链表存储的,那么每个哈希桶的数据量不会超过8个,这样当定位到某个哈希桶时,在该哈希桶继续查找也可以在O(1)时间内完成,下面看一种极端情况,所有的数据都在同一个桶里面(这种情况只在所有键值hash值相同的情况下,这种情况下查询的时间复杂度为O(lgn),比如下面给出的一个类,所有我们在设置hashmap的键值时需要特别注意),在hashmap的文档里面有这么一段描述,每个哈希桶中元素数量是成泊松分布的,

listSize = (exp(-0.5) * pow(0.5, k) / * factorial(k)),

不同数量出现的概率如下:

* 0:    0.60653066
* 1:    0.30326533
* 2:    0.07581633
* 3:    0.01263606
* 4:    0.00157952
* 5:    0.00015795
* 6:    0.00001316
* 7:    0.00000094
* 8:    0.00000006
大于8: <千万分之1

通过上面的统计来看,hashmap的键值正常(不同对象的hash值不同的情况),哈希桶数量超过8个概率低于千万分之一,所以我们通常认为hashmap的查询时间复杂度为O(1)

PS:

1、哈希冲突百分百的类

 /**
    测试哈希冲突的类,所有的对象都返回同样的hash值
   **/
    public static class Student{
        private String name;
        Student(String name){
            this.name = name;
        }
 
        @Override
        public int hashCode(){
            return 1;
        }
 
        @Override
        public boolean equals(Object obj){
            if(this == obj){
                return true;
            }
            if(obj == null){
                return false;
            }
            return this.name.equals(((Student)obj).name);
        }
    }

2、我们在实际使用hashmap时需要确保实现hashcode方法以及equals方法,否则不能作为hashmap的键值

3、在设置hashmap的键值hashcode方法时尽量保证较好的离散型

4、hashmap的键值需保证equals方法返回true时,hashcode必须相同,所以在实际中经常使用的键值类string,重写了equals以及hashcode方法

HashMap时间复杂度问题

HashMap底层采用了hash算法

根据 key 获得 hashCode 值

HashMap 初始有很多个类似于“桶”的数据结构,比如说预设了 10 个桶,通过 hashCode 经过一定的算法(这个算法必须是快速的)

得到这个 hashCode 应存在哪个桶中,然后内部生成 Map.Entry 对象将 key 和 value 存到桶中去。

所以一般情况下HashMap的插入和查找的时间复杂度都是O(1);

“hashmap查询时间复杂度为O(1)的原因是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程笔记网站,小编将为大家输出更多高质量的实用文章!


推荐阅读
  • 缓存这个东西就是为了提高运行速度的,由于缓存是在寸土寸金的内存里面,不是在硬盘里面,所以容量是很有限的。LRU这个算法就是把最近一次使用时间离现在时间最远的数据删除掉。先说说List:每 ... [详细]
  • 本篇文章给大家分享的是有关Java中怎么对HashMap按键值排序,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • HashTable与ConcurrentHashMap均可实现HashMap的功能,对外提供了键值对存储的数据结构。但是在内部结构及实现上有何区别,性能上的差异到底在哪里又是如何导致的 ... [详细]
  • Java之HashMap在多线程情况下导致死循环的问题
    PS:不得不说Java编程思想这本书是真心强大..学习内容:1.HashMap<K,V>在多线程的情况下出现的死循环现象当初学Java的时候只是知道HashMap< ... [详细]
  • 转载自:http:www.blogjava.netCarpenterLeearchive20160427430268.html总体介绍之所以把HashSet和HashMa ... [详细]
  • 将学生对象和学生的归属地通过键与值存储到map集合中。importjava.util.HashMap;importjava.util.Iterator;importjava.uti ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
author-avatar
阳光-假日
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有