1.HashMapå®ç°åç
2.HashMap实现原理一步一步分析(1-put方法源码整体过程)
3.LFU原理及代码实现
4.Redis7.0源码阅读:哈希表扩容、哈希哈希缩容以及rehash
5.HashMap和Hashtable有什么区别?链表链表
6.hash / hashtable(linux kernel 哈希表)
HashMapå®ç°åç
HashMapå¨å®é å¼åä¸ç¨å°çé¢çé常é«ï¼é¢è¯ä¸ä¹æ¯çç¹ãæ以å³å®åä¸ç¯æç« è¿è¡åæï¼å¸æ对æ³çæºç ç人起å°ä¸äºå¸®å©ï¼çä¹åéè¦å¯¹é¾è¡¨æ¯è¾çæã以ä¸é½æ¯æèªå·±çç解ï¼æ¬¢è¿è®¨è®ºï¼åçä¸å¥½è½»å·ã
HashMapä¸çæ°æ®ç»æ为æ£å表ï¼åååå¸è¡¨ãå¨è¿éæä¼å¯¹æ£å表è¿è¡ä¸ä¸ªç®åçä»ç»ï¼å¨æ¤ä¹åæ们éè¦å å顾ä¸ä¸ æ°ç»ãé¾è¡¨çä¼ç¼ºç¹ã
æ°ç»åé¾è¡¨çä¼ç¼ºç¹åå³äºä»ä»¬åèªå¨å åä¸åå¨ç模å¼ï¼ä¹å°±æ¯ç´æ¥ä½¿ç¨é¡ºåºåå¨æé¾å¼åå¨å¯¼è´çãæ 论æ¯æ°ç»è¿æ¯é¾è¡¨ï¼é½æææ¾ç缺ç¹ãèå¨å®é ä¸å¡ä¸ï¼æ们æ³è¦çå¾å¾æ¯å¯»åãå é¤ãæå ¥æ§è½é½å¾å¥½çæ°æ®ç»æï¼æ£å表就æ¯è¿æ ·ä¸ç§ç»æï¼å®å·§å¦çç»åäºæ°ç»ä¸é¾è¡¨çä¼ç¹ï¼å¹¶å°å ¶ç¼ºç¹å¼±åï¼å¹¶ä¸æ¯å®å ¨æ¶é¤ï¼
æ£å表çåæ³æ¯å°keyæ å°å°æ°ç»çæ个ä¸æ ï¼ååçæ¶åéè¿keyè·åå°ä¸æ ï¼indexï¼ç¶åéè¿ä¸æ ç´æ¥ååãé度æå¿«ï¼èå°keyæ å°å°ä¸æ éè¦ä½¿ç¨æ£åå½æ°ï¼åååå¸å½æ°ã说å°åå¸å½æ°å¯è½æ人已ç»æ³å°äºï¼å¦ä½å°keyæ å°å°æ°ç»çä¸æ ã
å¾ä¸è®¡ç®ä¸æ 使ç¨å°äºä»¥ä¸ä¸¤ä¸ªå½æ°ï¼
å¼å¾æ³¨æçæ¯ï¼ä¸æ 并ä¸æ¯éè¿hashå½æ°ç´æ¥å¾å°çï¼è®¡ç®ä¸æ è¿è¦å¯¹hashå¼åindex()å¤çã
Psï¼å¨æ£å表ä¸ï¼æ°ç»çæ ¼åå«å桶ï¼ä¸æ å«å桶å·ï¼æ¡¶å¯ä»¥å å«ä¸ä¸ªkey-value对ï¼ä¸ºäºæ¹ä¾¿ç解ï¼åæä¸ä¼ä½¿ç¨è¿ä¸¤ä¸ªåè¯ã
以ä¸æ¯åå¸ç¢°æç¸å ³ç说æï¼
以ä¸æ¯ä¸æ å²çªç¸å ³ç说æï¼
å¾å¤äººè®¤ä¸ºåå¸å¼ç碰æåä¸æ å²çªæ¯åä¸ä¸ªä¸è¥¿ï¼å ¶å®ä¸æ¯çï¼å®ä»¬çæ£ç¡®å ³ç³»æ¯è¿æ ·çï¼hashCodeåç碰æï¼åä¸æ ä¸å®å²çªï¼èä¸æ å²çªï¼hashCode并ä¸ä¸å®ç¢°æ
ä¸ææå°ï¼å¨jdk1.8以åHashMapçå®ç°æ¯æ£å表 = æ°ç» + é¾è¡¨ï¼ä½æ¯å°ç®å为æ¢æ们è¿æ²¡æçå°é¾è¡¨èµ·å°çä½ç¨ãäºå®ä¸ï¼HashMapå¼å ¥é¾è¡¨çç¨æå°±æ¯è§£å³ä¸æ å²çªã
ä¸å¾æ¯å¼å ¥é¾è¡¨åçæ£å表ï¼
å¦ä¸å¾æ示ï¼å·¦è¾¹çç«æ¡ï¼æ¯ä¸ä¸ªå¤§å°ä¸ºçæ°ç»ï¼å ¶ä¸åå¨çæ¯é¾è¡¨ç头ç»ç¹ï¼æ们ç¥éï¼æ¥æé¾è¡¨ç头ç»ç¹å³å¯è®¿é®æ´ä¸ªé¾è¡¨ï¼æ以认为è¿ä¸ªæ°ç»ä¸çæ¯ä¸ªä¸æ é½åå¨çä¸ä¸ªé¾è¡¨ãå ¶å ·ä½åæ³æ¯ï¼å¦æåç°ä¸æ å²çªï¼ååæå ¥çèç¹ä»¥é¾è¡¨çå½¢å¼è¿½å å°åä¸ä¸ªèç¹çåé¢ã
è¿ç§ä½¿ç¨é¾è¡¨è§£å³å²çªçæ¹æ³å«åï¼æé¾æ³ï¼åå«é¾å°åæ³ï¼ãHashMap使ç¨çå°±æ¯æé¾æ³ï¼æé¾æ³æ¯å²çªåç以åç解å³æ¹æ¡ã
Qï¼æäºæé¾æ³ï¼å°±ä¸ç¨æ å¿åçå²çªåï¼
Aï¼å¹¶ä¸æ¯ï¼ç±äºå²çªçèç¹ä¼ä¸åçå¨é¾è¡¨ä¸è¿½å ï¼å¤§éçå²çªä¼å¯¼è´å个é¾è¡¨è¿é¿ï¼ä½¿æ¥è¯¢æ§è½éä½ãæ以ä¸ä¸ªå¥½çæ£å表çå®ç°åºè¯¥ä»æºå¤´ä¸åå°å²çªåççå¯è½æ§ï¼å²çªåççæ¦çååå¸å½æ°è¿åå¼çååç¨åº¦æç´æ¥å ³ç³»ï¼å¾å°çåå¸å¼è¶ååï¼å²çªåççå¯è½æ§è¶å°ã为äºä½¿åå¸å¼æ´ååï¼HashMapå é¨åç¬å®ç°äºhash()æ¹æ³ã
以ä¸æ¯æ£å表çåå¨ç»æï¼ä½æ¯å¨è¢«è¿ç¨å°HashMapä¸æ¶è¿æå ¶ä»éè¦æ³¨æçå°æ¹ï¼è¿éä¼è¯¦ç»è¯´æã
ç°å¨æä»¬æ¸ æ¥äºæ£å表çåå¨ç»æï¼ç»å¿ç人åºè¯¥å·²ç»åç°äºä¸ä¸ªé®é¢ï¼Javaä¸æ°ç»çé¿åº¦æ¯åºå®çï¼æ 论åå¸å½æ°æ¯å¦ååï¼éçæå ¥å°æ£å表ä¸æ°æ®çå¢å¤ï¼å¨æ°ç»é¿åº¦ä¸åçæ åµä¸ï¼é¾è¡¨çé¿åº¦ä¼ä¸æå¢å ãè¿ä¼å¯¼è´é¾è¡¨æ¥è¯¢æ§è½ä¸ä½³ç缺ç¹åºç°å¨æ£å表ä¸ï¼ä»è使æ£å表失å»åæ¬çæä¹ã为äºè§£å³è¿ä¸ªé®é¢ï¼HashMapå¼å ¥äºæ©å®¹ä¸è´è½½å åã
以ä¸æ¯åæ©å®¹ç¸å ³çä¸äºæ¦å¿µå解éï¼
Psï¼æ©å®¹è¦éæ°è®¡ç®ä¸æ ï¼æ©å®¹è¦éæ°è®¡ç®ä¸æ ï¼æ©å®¹è¦éæ°è®¡ç®ä¸æ ï¼å 为ä¸æ ç计ç®åæ°ç»é¿åº¦æå ³ï¼é¿åº¦æ¹åï¼ä¸æ ä¹åºå½éæ°è®¡ç®ã
å¨1.8åå ¶ä»¥ä¸çjdkçæ¬ä¸ï¼HashMapåå¼å ¥äºçº¢é»æ ã
红é»æ çå¼å ¥è¢«ç¨äºæ¿æ¢é¾è¡¨ï¼ä¸æ说å°ï¼å¦æå²çªè¿å¤ï¼ä¼å¯¼è´é¾è¡¨è¿é¿ï¼éä½æ¥è¯¢æ§è½ï¼ååçhashå½æ°è½ææçç¼è§£å²çªè¿å¤ï¼ä½æ¯å¹¶ä¸è½å®å ¨é¿å ãæ以HashMapå å ¥äºå¦ä¸ç§è§£å³æ¹æ¡ï¼å¨å¾é¾è¡¨å追å èç¹æ¶ï¼å¦æåç°é¾è¡¨é¿åº¦è¾¾å°8ï¼å°±ä¼å°é¾è¡¨è½¬ä¸ºçº¢é»æ ï¼ä»¥æ¤æåæ¥è¯¢çæ§è½ã
HashMap实现原理一步一步分析(1-put方法源码整体过程)
本文分享了HashMap内部的实现原理,重点解析了哈希(hash)、源码散列表(hash table)、哈希哈希哈希码(hashcode)以及hashCode()方法等基本概念。链表链表
哈希(hash)是源码绝品指标源码将任意长度的输入通过散列算法转换为固定长度输出的过程,建立一一对应关系。哈希哈希常见算法包括MD5加密和ASCII码表。链表链表
散列表(hash table)是源码一种数据结构,通过关键码值映射到表中特定位置进行快速访问。哈希哈希
哈希码(hashcode)是链表链表散列表中对象的存储位置标识,用于查找效率。源码
Object类中的哈希哈希hashCode()方法用于获取对象的哈希码值,以在散列存储结构中确定对象存储地址。链表链表
在存储字母时,源码使用哈希码值对数组大小取模以适应存储范围,防止哈希碰撞。
HashMap在JDK1.7中使用数组+链表结构,而JDK1.8引入了红黑树以优化性能。
HashMap内部数据结构包含数组和Entry对象,数组用于存储Entry对象,Entry对象用于存储键值对。
在put方法中,首先判断数组是否为空并初始化,然后计算键的哈希码值对数组长度取模,用于定位存储位置。as608源码如果发生哈希碰撞,使用链表解决。
本文详细介绍了HashMap的存储机制,包括数组+链表的实现方式,以及如何处理哈希碰撞。后续文章将继续深入探讨HashMap的其他特性,如数组长度的优化、多线程环境下的性能优化和红黑树的引入。
LFU原理及代码实现
LFU的原理基于一个概念,即访问频率作为选择淘汰对象的依据。与LRU(Least Recently Used)不同,LFU更侧重于访问频次,它维护一个元素的访问频率,并基于频率进行淘汰。
LFU由两个主要组件构成:一个列表和一个哈希表。列表内包含两层结构:第一层用于区分元素的访问频率,第二层则在同频率下实现LRU(Least Recently Used)策略,以确保最新访问的元素位于链表的头部。
哈希表是一个无序映射,其键为LFU元素的key,值为一个结构体。该结构体包含两个部分:第一部分表示元素在列表中第一层的位置,第二部分则对应第二层在LRU链表中的位置。如此设计,可在常数时间内访问和更新元素信息。营销软件源码出售
核心策略在于,每当元素被访问,其频率将递增,并相应地将元素移动至更高频率的LRU链表头部。如果不存在对应频率的链表,则需新建。这种动态更新机制确保了频率更高、访问更频繁的元素得到优先处理。
整体代码实现如下,旨在清晰展现LFU原理和逻辑:
Redis7.0源码阅读:哈希表扩容、缩容以及rehash
当哈希值相同发生冲突时,Redis 使用链表法解决,将冲突的键值对通过链表连接,但随着数据量增加,冲突加剧,查找效率降低。负载因子衡量冲突程度,负载因子越大,冲突越严重。为优化性能,Redis 需适时扩容,将新增键值对放入新哈希桶,减少冲突。
扩容发生在 setCommand 部分,其中 dictKeyIndex 获取键值对索引,源码十六进制判断是否需要扩容。_dictExpandIfNeeded 函数执行扩容逻辑,条件包括:不在 rehash 过程中,哈希表初始大小为0时需扩容,或负载因子大于1且允许扩容或负载因子超过阈值。
扩容大小依据当前键值对数量计算,如哈希表长度为4,实际有9个键值对,扩容至(最小的2的n次幂大于9)。子进程存在时,dict_can_resize 为0,反之为1。fork 子进程用于写时复制,确保持久化操作的稳定性。
哈希表缩容由 tryResizeHashTables 判断负载因子是否小于0.1,条件满足则重新调整大小。此操作在数据库定时检查,且无子进程时执行。
rehash 是为解决链式哈希效率问题,通过增加哈希桶数量分散存储,减少冲突。dictRehash 函数完成这一任务,移动键值对至新哈希表,使用位运算优化哈希计算。渐进式 rehash 通过分步操作,迷你世界资源码减少响应时间,适应不同负载情况。定时任务检测服务器空闲时,进行大步挪动哈希桶。
在 rehash 过程中,数据查询首先在原始哈希表进行,若未找到,则在新哈希表中查找。rehash 完成后,哈希表结构调整,原始表指向新表,新表内容返回原始表,实现 rehash 结果的整合。
综上所述,Redis 通过哈希表的扩容、缩容以及 rehash 动态调整哈希桶大小,优化查找效率,确保数据存储与检索的高效性。这不仅提高了 Redis 的性能,也为复杂数据存储与管理提供了有力支持。
HashMap和Hashtable有什么区别?
HashMap和Hashtable都是用于实现基于键值对的映射数据结构的类。它们主要区别在于线程安全性、null值的处理和迭代器的顺序。
Hashtable是线程安全的,其方法都是同步的,如果多个线程同时访问一个实例,数据可能不一致。相反,HashMap不是线程安全的。
在null值处理上,Hashtable不允许键或值为null,否则会抛出异常。而HashMap允许键或值为null,使用特殊null键和null值。
HashMap迭代器不保证遍历元素顺序,而Hashtable迭代器保证按插入顺序遍历。
下面是HashMap和Hashtable的代码示例:
输出结果如下:
注意,由于Hashtable不允许null键或值,以下代码会抛出异常。而HashMap允许键或值为null。
HashMap和Hashtable实现原理不同,HashMap使用哈希表,Hashtable使用哈希表加链表实现。HashMap通常比Hashtable更快,但不是线程安全的。
在使用HashMap时,如果需要保证元素顺序,应使用LinkedHashMap。避免使用Enumeration迭代器,推荐使用Iterator。
使用HashMap时,应根据实际情况选择合适的初始容量和负载因子,避免频繁扩容和重新散列,影响性能。
hash / hashtable(linux kernel 哈希表)
哈希表,或称为散列表,是一种高效的数据结构,因其插入和查找速度的优势而备受关注。然而,其空间利用率并不固定,需要权衡。让我们通过实例来深入理解它的作用和工作原理。
想象一个场景:我们需要高效地存储和访问大量数据。首先,常规的数组方法,如普通数组和有序数组,虽然插入简单,但查找效率低,尤其是在数据量较大时。例如,查找可能需要对数千个元素进行比较。有序数组通过牺牲增删效率来提升查询,但数组空间固定且可能浪费大量资源。
链表提供了更灵活的增删操作,但随机访问困难,适合数据频繁变动的情况。红黑树在查询和增删效率上表现优秀,但此处暂不讨论。庞大的数组虽然理论上能快速查找,但实际操作中难以实现,因为它需要预先预估并准备极大数据空间。
这时,哈希表登场了。它利用哈希函数将数据映射到一个较小的数组中,即使存在冲突(不同数据映射到同一地址),通过链表解决,仍然能显著提升查找效率。例如,即使身份证号的哈希结果可能有重复,但实际冲突相对较少,通过链表链接,平均查找次数大大减少。
使用哈希表包括简单的步骤:包含头文件,声明和初始化哈希表,添加节点,以及通过哈希键查找节点。在实际源码中,如Linux kernel的hash.h和hashtable.h文件,哈希表的初始化和操作都是基于这些步骤进行的。
总结来说,哈希表在大数据场景中通过计算直接定位数据,显著提高效率,尤其是在数据量增大时。如果你对Linux kernel的哈希表实现感兴趣,可以关注我的专栏RTFSC,深入探讨更多源码细节。
一目了然,Hash算法及HashMap底层实现原理
Hash算法和HashMap底层实现原理概述:
哈希表以其高效查询和插入操作而备受青睐。其核心是将(key, value)对通过哈希函数映射到数组的特定位置,查询时间复杂度达到理想状态的O(1)。哈希表结构结合了数组、链表和红黑树,数组用于基本存储,链表或平衡二叉树用于处理碰撞。数组的查询和插入复杂度为O(1),而链表或平衡二叉树的相应操作为O(n)或O(lgn)。
具体实现中,首先通过哈希算法,如默认使用key的hashCode,计算得到一个整数hash值。然后,通过取余操作确定在数组中的存储位置。当发生碰撞,即多个key映射到同一位置,HashMap采用开放寻址法或链式地址解决,如Java默认使用拉链法。开放寻址法通过在数组中寻找空余位置,链式地址则使用链表结构存储冲突的结点,查询时遍历链表。
HashMap以数组为基础,每个元素是链表的头节点,Put方法根据Key的哈希值定位并插入链表,Get方法则通过哈希映射和链表遍历找到对应的Value。HashMap初始长度为的2的幂,通过位运算确保哈希分布均匀,避免过多的碰撞。
理解Hash算法的关键在于生成的哈希值的均匀分布,以及如何通过位运算来快速定位数组位置。通过深入研究,您将能更好地掌握这些复杂的底层实现机制。