创建一个HashMap对象,用于存储身份z和人的键值对(人是一个类别)

创建一个HashMap对象,用于存储身份z和人的键值对(人是一个类别),第1张

Map<String,Persson> map = new HashMap<String,Person>;

Person p = new Person();

mapput("身份z号",p);

得到的时候可以

mapget("身份z号");

HashMap<>在Java语言中是一种常用的集合类,它提供了存储键值对的功能,在里面只写键值是没有意义的,因为键和值是需要配对的,必须同时提供键和值才能完成键值对的存储和获取。

HashMap(jdk 18)

  使用哈希表存储键值对,底层是一个存储Node的table数组。其基本的运行逻辑是,table数组的每一个元素是一个槽,用于存储Node对象,向Hash表中插入键值对时,首先计算键的hash值,并对数组容量(即数组长度)取余,定位该键值对应放在哪个槽中,若槽中已经存在元素(即哈希冲突),将Node节点插入到冲突链表尾端,当该槽中结点超过一定数量(默认为8)并且哈希表容量超过一定值(默认为64)时,对该链表进行树化。低于一定数量(默认为6)后进行resize时,树形结构又会链表化。当哈希表的总节点数超过阈值时,对哈希表进行扩容,容量翻倍。

由于哈希表需要用到key的哈希函数,因此对于自定义类作为key使用哈希表时,需要重写哈希函数,保证相等的key哈希值相同。

由于扩容或树化过程Node节点的位置会发生改变,因此哈希表是无序的,不同时期遍历同一张哈希表,得到的节点顺序会不同。

成员变量

    Hash表的成员变量主要有存储键值对的table数组,size,装载因子loadFactory,阈值theshold,容量capacity。

table数组:

哈希表的实质就是table数组,它用来存储键值对。哈希表中内部定义了Node类来封装键值对。

 Node类实现了Map的Entry接口。包括key,value,下一个Node指针和key的hash值。

 容量Capacity:

HashMap中没有专门的属性存储容量,容量等于tablelenth,即数组的长度,默认初始化容量为16。初始化时,可以指定哈希表容量,但容量必须是2的整数次幂,在初始化过程中,会调用tableSizeFor函数,得到一个不小于指定容量的2的整数次幂,暂时存入到threshold中。

注意,若容量设置过大,那么遍历整个哈希表需要耗费更多的时间。

    阈值threshold:

指定当前hash表最多存储多少个键值对,当size超过阈值时,hash表进行扩容,扩容后容量翻倍。

   loadFactory:

threshold=capacityloadFactory。

装填因子的大小决定了哈希表存储键值对数量的能力,它直接影响哈希表的查找性能。初始化时可以指定loadFactory的值,默认为075。

 初始化过程

哈希表有3个构造函数,用户可以指定哈希表的初始容量和装填因子,但初始化过程只是简单填入这两个参数,table数组并没有初始化。注意,这里的initialCapacity会向上取2的整数次幂并暂时保存到threshold中。

table数组的初始化是在第一次插入键值对时触发,实际在resize函数中进行初始化。

hash过程与下标计算

哈希表是通过key的哈希值决定Node放入哪个槽中, 在java8中 ,hash表没有直接用key的哈希值,而是自定义了hash函数。

哈希表中的key可以为null,若为null,哈希值为0,否则哈希值(一共32位)的高16位不变,低16位与高16位进行异或 *** 作,得到新的哈希值。(h >>> 16,表示无符号右移16位,高位补0,任何数跟0异或都是其本身,因此key的hash值高16位不变。)

之所以这样处理,是与table的下标计算有关

因为,table的长度都是2的幂,因此index仅与hash值的低n位有关(n-1为0000011111的形式),hash值的高位都被与 *** 作置为0了,相当于hash值对n取余。

由于index仅与hash值的低n位有关,把哈希值的低16位与高16位进行异或处理,可以让Node节点能更随机均匀得放入哈希表中。

get函数:

V  get(Object key) 通过给定的key查找value

先计算key的哈希值,找到对应的槽,遍历该槽中所有结点,如果结点中的key与查找的key相同或相等,则返回value值,否则返回null。

注意,如果返回值是null,并不一定是没有这种KV映射,也有可能是该key映射的值value是null,即key-null的映射。也就是说,使用get方法并不能判断这个key是否存在,只能通过containsKey方法来实现。

put函数

V put(K key, V value) 存放键值对

计算key的哈希值,找到哈希表中对应的槽,遍历该链表,如果发现已经存在包含该key的Node,则把新的value放入该结点中,返回该结点的旧value值(旧value可能是null),如果没有找到,则创建新结点插入到 链表尾端 (java7使用的是头插法),返回null。插入结点后需要判断该链表是否需要树化,并且判断整个哈希表是否需要扩容。

由该算法可以看出,哈希表中不会有两个key相同的键值对。

resize函数

    resize函数用来初始化或扩容table数组。主要做了两件事。

1根据table数组是否为空判断初始化还是扩容,计算出相应的newCap和newThr,新建table数组并设置新的threshold。

2若是进行扩容,则需要将原数组中的Node移植到新的数组中。

由于数组扩容,原来键值对可能存储在新数组不同的槽中。但由于键值对位置是对数组容量取余(index=hash(key)&(Capacity-1)),由于Capacity固定为2的整数次幂,并新的Capacity(newCap)是旧的两倍(oldCap)。因此,只需要判断每个Node中的hash值在oldCap二进制那一位上是否为0(hash&oldCap==0),若为0,对newCap取余值与oldCap相同,Node在新数组中槽的位置不变,若为1,新的位置是就得位置加一个oldCap值。

因此hashMap的移植算法是,遍历旧的槽:

若槽为空,跳过。

若槽只有一个Node,计算该Node在新数组中的位置,放入新槽中。

若槽是一个链表,则遍历这个链表,分别用loHead,loTail,hiHead,hiTail两组指针建立两个链表,把hash值oldCap位为0的Node节点放入lo链表中,hash值oldCap位为1的节点放入hi链表中,之后将两个链表分别插入到新数组中,实现原键值对的移植。

lo链表放入新数组原来位置,hi链表放入新数组原来位置+oldCap中

树化过程 :

当一个槽中结点过多时,哈希表会将链表转换为红黑树,此处挖个坑。

[总结] java8中hashMap的实现原理与7之间的区别:

1hash值的计算方法不同 2链表采用尾插法,之前是头插法 3加入了红黑树结构

应该是这句 if(element[1]!=null){ 报的异常吧你上面按 & 进行分割,有一段分割出来是 e= 所以当你再按钮 = 分割的时候,element[1]会出现下标越界

HashMap,中文名哈希映射,HashMap是一个用于存储Key-Value键值对的集合,每一个键值对也叫做Entry。这些个键值对(Entry)分散存储在一个数组当中,这个数组就是HashMap的主干。HashMap数组每一个元素的初始值都是Null。

HashMap是基于哈希表的 Map 接口的实现。此实现提供所有可选的映射 *** 作,并允许使用 null 值和 null 键。(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

扩展资料:

因为HashMap的长度是有限的,当插入的Entry越来越多时,再完美的Hash函数也难免会出现index冲突的情况。

HashMap数组的每一个元素不止是一个Entry对象,也是一个链表的头节点。每一个Entry对象通过Next指针指向它的下一个Entry节点。当新来的Entry映射到冲突的数组位置时,只需要插入到对应的链表即可。

参考资料来源:

百度百科-Hashmap

一,存储方式: Java中的HashMap是以键值对(key-value)的形式存储元素的。

二,调用原理: HashMap需要一个hash函数,它使用hashCode()和equals()方法来向集合/从集合添加和检索元素。当调用put()方法的时候,HashMap会计算key的hash值,然后把键值对存储在集合中合适的索引上。如果key已经存在了,value会被更新成新值。

三,其他热性: HashMap的一些重要的特性是它的容量(capacity),负载因子(load factor)和扩容极限(threshold resizing)。

以上就是关于创建一个HashMap对象,用于存储身份z和人的键值对(人是一个类别)全部的内容,包括:创建一个HashMap对象,用于存储身份z和人的键值对(人是一个类别)、hashmap<>里面只写key、HashMap源码分析等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/9502835.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-29
下一篇 2023-04-29

发表评论

登录后才能评论

评论列表(0条)

保存