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

上面就是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;}@Overridepublic int hashCode(){return 1;}@Overridepublic 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为什么查询时间复杂度为O(1)相关推荐

  1. 【数据结构】什么是哈希表?为什么哈希表的查询时间复杂度是O(1)?

    大家好,我是卷心菜,可以叫我菜菜,大二学生一枚.本篇主要讲解一种数据结构:哈希表.如果您看完文章有所收获,可以三连支持博主哦~,嘻嘻. 文章目录 一.前言 二.数组 三.哈希表 1.百度百科 2.问题 ...

  2. 20180316 数组查询时间复杂度

    在一个元素个数为N的数组里,找到升序排在N/5位置的元素的最优算法时间复杂度是 O(n) O(n log n) O(n (log n)2) O(n 3/2) 答案 A 基数排序 桶排序 基数排序 BF ...

  3. 字典树查询时间复杂度

    一 概述 又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计. 二 优点 利用字符串 ...

  4. Android架构思考(模块化、多进程)

    Android架构思考(模块化.多进程) Dec 28, 2016| Android | 4777 Hits 15条评论 关于模块化(组件化)这个问题,我想每个开发者可能都认真的思考过.随着项目的开发 ...

  5. C++---布隆过滤器

    我们在玩手机的时候,软件会给我们推送一些新消息,软件如何保证我们哪些消息看过,哪些消息没看过呢? 解决办法:用一个服务器记录我们看过的内容,为了保证能够快速查询,我们可以使用哈希表存储用户信息,但是浪 ...

  6. 记一次蚂蚁金服的面试经历

    2015在实习的时候,当时一个一起实习的朋友在2019年3月份的时候突然在微信上找我,问我要不要面试下蚂蚁金服.问了下相关信息才知道他在2018年11月的时候进到蚂蚁金服,现在招人就想到了我,问我要不 ...

  7. HashMap的时间复杂度是O(1)

    今天在面试的时候说到HashMap,面试官问了这么一个问题:你说HashMap的get迭代了一个链表,那怎么保证HashMap的时间复杂度O(1)?链表的查找的时间复杂度又是多少? 在这之前我是阅读过 ...

  8. 查询已有链表的hashmap_原创 | 面试不再慌,看完这篇保证让你写HashMap跟玩一样...

    点击上方蓝色小字,关注"码农小黑屋" 重磅干货,第一时间送达 今天这篇文章给大家讲讲hashmap,这个号称是所有Java工程师都会的数据结构.为什么说是所有Java工程师都会呢, ...

  9. mysql查询索引数组_mysql-索引

    索引模型: hash,有序数组,搜索树 1,hash: key,value存储.存储结构类似于Java7 的hashmap. 同一节点使用链表的形式存储.适合单个等值查询,不适用于范围查询 2,有序数 ...

最新文章

  1. 《Adobe Flash Professional CC经典教程》——1.3 使用“库”面板
  2. pythonweb开发-Web | 浅谈用Python进行Web开发
  3. proto 指定字段json名_比json快5倍的protobuf了解一下
  4. python 3.6.5编译安装_Centos7下编译安装python3.6.5
  5. linux运维适合女生么,女生真的不适合做IT行业吗?Linux运维适合女生学习吗?
  6. linux游戏调试,LINUX游戏服务器的安装与调试.doc
  7. Maven系列2--pom.xml 配置详解
  8. 修改oracle重做日志文件大小
  9. JavaScript学习初步
  10. 突发!Spring疑似沦陷了。。。
  11. 2022年起重机司机(限桥式起重机)复训题库模拟考试平台操作
  12. jconsole使用
  13. JAVA实现Excel照相机功能_用Excel照相机功能在Excel中显示和调用图片的方法
  14. Winhex的使用(慢慢更
  15. 数学概念: 导数和切线方程
  16. k8s calico-node错误日志 listen tcp: lookup localhost on ip:53: no such host
  17. ATEN CS22DP 2端口USB DisplayPort带线式KVM多电脑切换器 (外接式切换按键)
  18. MATLAB演示元胞自动机算法
  19. 计算机基础实验4,计算机基础实验 3-4 实验报告
  20. 国家名称映射和省市名称映射

热门文章

  1. marsonic 瀑布流问题 获取js图片原始尺寸的方法
  2. yum-downloadonly软件包
  3. 网页禁止进行复制粘贴操作怎么破解?
  4. offsetWidth与offsetLeft
  5. blas daxpy dcopy函数的使用
  6. SSO单点登录,实现对接SAML 协议对接IDP, 实现可拆解的SP服务
  7. python设置字符_python字符串操作
  8. win10下Visual Studio 2012 update4、AutoCAD 2016和二次开发插件ObjectARX2016环境安装及配置
  9. Intellij IDEA 中一次性折叠所有Java代码的快捷键设置 collapse all
  10. dispose 模式 java_C#使用Dispose模式实现手动对资源的释放