- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章HashMap原理的深入理解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
hashing(散列法或哈希法)的概念 。
散列法(hashing)是一种将字符组成的字符串转换为固定长度(一般是更短长度)的数值或索引值的方法,称为散列法,也叫哈希法。由于通过更短的哈希值比用原始值进行数据库搜索更快,这种方法一般用来在数据库中建立索引并进行搜索,同时还用在各种解密算法中.
hashmap概念和底层结构 。
hashmap是基于哈希表的map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。hashmap储存的是键值对,hashmap很快。此类不保证映射的顺序,特别是它不保证该顺序恒久不变.
hashmap实际上是一个“链表散列”的数据结构,即数组和链表的结合体.
数组:存储区间连续,占用内存严重,寻址容易,插入删除困难; 链表:存储区间离散,占用内存比较宽松,寻址困难,插入删除容易; hashmap综合应用了这两种数据结构,实现了寻址容易,插入删除也容易.
hashmap的结构示意图如下:
hashmap的基本存储原理以及存储内容的组成 。
基本原理:先声明一个下标范围比较大的数组来存储元素。另外设计一个哈希函数(也叫做散列函数)来获得每一个元素的key(关键字)的函数值(即数组下标,hash值)相对应,数组存储的元素是一个entry类,这个类有三个数据域,key、value(键值对),next(指向下一个entry).
例如, 第一个键值对a进来。通过计算其key的hash得到的index=0。记做:entry[0] = a。 第二个键值对b,通过计算其index也等于0, hashmap会将b.next =a,entry[0] =b, 第三个键值对 c,index也等于0,那么c.next = b,entry[0] = c;这样我们发现index=0的地方事实上存取了a,b,c三个键值对,它们通过next这个属性链接在一起。我们可以将这个地方称为桶。 对于不同的元素,可能计算出了相同的函数值,这样就产生了“冲突”,这就需要解决冲突,“直接定址”与“解决冲突”是哈希表的两大特点.
hashmap的工作原理以及存取方法过程 。
hashmap的工作原理 :hashmap是基于散列法(又称哈希法hashing)的原理,使用put(key, value)存储对象到hashmap中,使用get(key)从hashmap中获取对象。当我们给put()方法传递键和值时,我们先对键调用hashcode()方法,返回的hashcode用于找到bucket(桶)位置来储存entry对象。”hashmap是在bucket中储存键对象和值对象,作为map.entry。并不是仅仅只在bucket中存储值.
hashmap具体的存取过程如下: put键值对的方法的过程是:
get值方法的过程是
1、指定key 通过hash函数得到key的hash值 int hash=key.hashcode(),
2、调用内部方法 getnode(),得到桶号(一般都为hash值对桶数求模) int index =hash%entry[].length,
3、比较桶的内部元素是否与key相等,若都不相等,则没有找到。相等,则取出相等记录的value.
4、如果得到 key 所在的桶的头结点恰好是红黑树节点,就调用红黑树节点的 gettreenode() 方法,否则就遍历链表节点。gettreenode 方法使通过调用树形节点的 find()方法进行查找。由于之前添加时已经保证这个树是有序的,因此查找时基本就是折半查找,效率很高.
5、如果对比节点的哈希值和要查找的哈希值相等,就会判断 key 是否相等,相等就直接返回;不相等就从子树中递归查找.
hashmap中直接地址用hash函数生成;解决冲突,用比较函数解决。如果每个桶内部只有一个元素,那么查找的时候只有一次比较。当许多桶内没有值时,许多查询就会更快了(指查不到的时候).
hashmap中的碰撞探测(collision detection)以及碰撞的解决方法 。
当两个对象的hashcode相同时,它们的bucket位置相同,‘碰撞'会发生。因为hashmap使用linkedlist存储对象,这个entry(包含有键值对的map.entry对象)会存储在linkedlist中。这两个对象就算hashcode相同,但是它们可能并不相等。 那如何获取这两个对象的值呢?当我们调用get()方法,hashmap会使用键对象的hashcode找到bucket位置,遍历linkedlist直到找到值对象。找到bucket位置之后,会调用keys.equals()方法去找到linkedlist中正确的节点,最终找到要找的值对象使用不可变的、声明作final的对象,并且采用合适的equals()和hashcode()方法的话,将会减少碰撞的发生,提高效率。不可变性使得能够缓存不同键的hashcode,这将提高整个获取对象的速度,使用string,interger这样的wrapper类作为键是非常好的选择.
如何重新调整hashmap的大小 。
“如果hashmap的大小超过了负载因子(load factor)定义的容量,怎么办?” 。
默认的负载因子大小为0.75,也就是说,当一个map填满了75%的bucket时候,和其它集合类(如arraylist等)一样,将会创建原来hashmap大小的两倍的bucket数组,来重新调整map的大小,并将原来的对象放入新的bucket数组中。这个过程叫作rehashing,因为它调用hash方法找到新的bucket位置.
以上所述是小编给大家介绍的hashmap原理的理解详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我网站的支持! 。
最后此篇关于HashMap原理的深入理解的文章就讲到这里了,如果你想了解更多关于HashMap原理的深入理解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
最近做一个项目,由于是在别人框架里开发app,导致了很多限制,其中一个就是不能直接引用webservice 。 我们都知道,调用webserivice 最简单的方法就是在 "引用"
这是SDL2代码的一部分 SDL主函数 int main(int argc,char *argv[]) { ... ... bool quit=false; S
c 中的函数: PHPAPI char *php_pcre_replace(char *regex, int regex_len, ch
我有以下映射: public class SecurityMap : ClassMap { public SecurityMap() {
我在vue-lic3中使用了SCSS,但是有一个奇怪的错误,使用/ deep /会报告错误,我不想看到它。 代码运行环境 vue-cli3 + vant + scss 的CSS /deep/ .van
我在深入阅读 C# 时遇到了这个我能理解的内容: 当它被限制为引用类型时,执行的比较类型完全取决于类型参数被限制为什么。 但是不能理解这个: 如果进一步限制派生自重载 == 和 != 运算符的特定类型
Closed. This question is opinion-based。它当前不接受答案。 想改善这个问题吗?更新问题,以便editing this post用事实和引用来回答。 3年前关闭。
有人可以详细介绍关于自赋值的运算符重载中的 *this 和 const 例如: Class& Class::operator=(const Class& other) { a = other.
在向树中插入新节点时,如何填充闭包表的深度/长度列? ancestor 和 descendant 中的值是来自另一个表的 ID,表示要以树结构排列的页面。 关闭表: ancestor desce
现在我正在阅读“深入了解 C#”。缺少的一件事是完成一章后我可以解决的一系列问题。那会帮助我理解我刚刚学到的概念。 哪里可以找到适合 C#3.0 的问题集? 谢谢 最佳答案 你可以试试LINQ 101
TypeScript 给 JavaScript 扩展了类型的语法,我们可以给变量加上类型,在编译期间会做类型检查,配合编辑器还能做更准确的智能提示。此外,TypeScript 还支持了高级类型用
是否有一个单行代码来获取生成器并生成该生成器中的所有元素?例如: def Yearly(year): yield YEARLY_HEADER for month in range(1, 13)
所以我阅读了一些与“什么是方法组”相关的 StackOverflow 问题以及其他互联网文章,它们在底线都说了同样的话——方法组是“一组重载方法” ". 但是,在阅读 Jon Skeet 的“C# 深
有什么方法可以从子组件中获取子组件吗? 想象一下以下组件树: 应用程序 问题 问题选项(包含复选框) 问题选项(包含复选框) 问题选项(包含复选框) 我想从 App 访问问题选项以选中所有复选框。 参
class_eval 和 instance_eval 在定义方法等情况下是完全可以预测的。我也理解类的实例和类的单例(又名特征类)之间的区别。 但是 我无法弄清楚以下唯一的事情:比方说,出于某些策略目
我想出了如何将符号 rwx 部分读取/转换为 421 个八进制部分,这非常简单。但是当涉及到特殊字符时,我感到非常困惑。我们知道 -r-xr---wx 转换为 0543,但 -r-sr---wt 或
我怀疑我系统的 Java 版本有问题。某些应用程序出现段错误或内存不足或存在链接错误。如果我从源代码安装了 JDK,我会做类似“make test”的事情,看看哪些测试失败了。但是,看起来从源代码构建
如何克隆一个 repo(使用 libgit2 ) 我想做什么git clone确实,但有 libgit2 .我可能要问的是什么 git clone确实很深入。 这是我目前正在做的: 初始化一个repo
00、头痛的JS闭包、词法作用域? 被JavaScript的闭包、上下文、嵌套函数、this搞得很头痛,这语言设计的,感觉比较混乱,先勉强理解总结一下😂😂😂.
我开始玩 lubridate R 中的包。我注意到 now(tzone="EST")计算为: [1] "2015-08-25 13:01:08 EST" 而 now(tzone="PST")导致警告:
我是一名优秀的程序员,十分优秀!