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

java学习hashmap(2)

HashMap的规约JavaDocs中HashMap的spec是这么写的:Hashtablebased implementationoftheMapinterface.Thisim

HashMap的规约

JavaDocs中HashMap的spec是这么写的:


Hash table based implementation of the Map interface. This implementation provides all of the optional map operations, and permits null values and the null key. (The HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized and permits nulls.) This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.


这里头可提取出几个关键的信息:



  • 基于Map接口实现

  • 允许null键/值

  • 非同步

  • 不保证有序(如插入的顺序)

  • 不保证顺序不随时间变化。

这些问题在上篇都已经基本解释清楚了。下篇中,我们顺着HashMap的规约继续往下探索。


两个因子

有两个因子直接影响HashMap的效率,



  • 初始容量(initial capacity)。容量是指哈希表中桶的数量,而初始容量顾名思义就是HashMap实例创建时的最初容量。

  • 载入因子(Load factor)。含义在上篇已经阐述。

JavaDocs的原文对这两个因子是这样描述的:




  • Initial capacity. The capacity is the number of buckets in the hash table, The initial capacity is simply the capacity at the time the hash table is created.

  • Load factor. The load factor is a measure of how full the hash table is allowed to get before its capacity is automatically increased.


简单的说,容量(Capacity)就是桶(buckets)的数目,载入因子就是有数据的桶占所有桶的最大比例。如果对迭代性能要求很高的话不要把容量设置过大,也不要把载入因子设置过小。当有数据的桶的数目(即HashMap中元素的个数)大于Capacity * LoadFactor时就需要调整桶的数目为当前的两倍,也就是上篇所说的扩张。


初始容量

HashMap的默认初始容量为16。把它设成2的幂次是有意为之。我们再回顾一下index的计算:

index = hash(Key) & (length - 1)

因为length是,所以length - 1是,也就是个1,index就相当于是hash(Key)的最后位。这样,只要保证hash(Key)是均匀的,index的分布也就一定是均匀的。此外,这样设计算法使得可以用位运算计算index,避免了取模等效率低下的运算方式,提高了运算效率。

另外,需要注意的是,hash(Key)并不是hashCode(Key)hash方法的定义如下:

static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

 

可以看到这个函数大概的作用就是:高16位不变,低16位和高16位做了一个异或。其中代码注释是这样写的:


Computes key.hashCode() and spreads (XORs) higher bits of hash to lower. Because the table uses power-of-two masking, sets of hashes that vary only in bits above the current mask will always collide. (Among known examples are sets of Float keys holding consecutive whole numbers in small tables.) So we apply a transform that spreads the impact of higher bits downward. There is a tradeoff between speed, utility, and quality of bit-spreading. Because many common sets of hashes are already reasonably distributed (so don’t benefit from spreading), and because we use trees to handle large sets of collisions in bins, we just XOR some shifted bits in the cheapest possible way to reduce systematic lossage, as well as to incorporate impact of the highest bits that would otherwise never be used in index calculations because of table bounds.


也就是说,设计者认为直接用hashCode(Key)的值很容易发生碰撞。为什么这么说呢?不妨思考一下,在为15(0x1111)时,其实散列真正生效的只是低4位,当然容易碰撞了。

因此,设计者采取了顾全大局的方法(综合考虑了速度、作用、质量),即把高16位和低16位异或了一下(也就是hash方法的作用)。设计者还解释到因为现在大多数的hashCode的分布已经很不错了,就算是发生了碰撞也用的红黑树去做了(下文会提到)。仅仅异或一下,既减少了系统的开销,也不会造成的因为高位没有参与下标的计算而引起的碰撞。

至于为什么偏偏设成2的4次幂,一般认为没什么特别的理由,用4次幂可能只是因为作者认为16这个初始容量是能符合常用的情景而已。



推荐阅读
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 展开全部下面的代码是创建一个立方体Thisexamplescreatesanddisplaysasimplebox.#Thefirstlineloadstheinit_disp ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了最长上升子序列问题的一个变种解法,通过记录拐点的位置,将问题拆分为左右两个LIS问题。详细讲解了算法的实现过程,并给出了相应的代码。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
author-avatar
mobiledu2502903717
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有