集合源码解读

HashMap:

首先,HashMap的底层数据结构是数组+链表,它的底层是由一个Entry数组组成的。Entry对象是一个链式结构,它里面有四个属性,分别是:key、value、next(链式结构中的下一个对象)、Hash值。

HashMap里面有几个成员变量,分别定义了一些默认的数值,比如定义了默认的长度是1<<4也就是16,还定义了默认的加载因子是0.75f,HashMap他有一个扩容机制,当数组中的元素达到加载因子所定义的密度时,为了保证每条链上的对象不会过多而影响查询速度,HashMap中的Entry数组会进行扩容,每次扩大为之前的2倍,实际上这是一种空间换时间的做法。

HashMap中有很多构造方法,但是无论我们通过哪个构造方法创建HashMap最终调用的都是两个参的有参构造。在源码里对传入的参数做了一些安全性验证,但是此时HashMap中的Entry数组并没有开辟空间。而是在第一次调用put方法存值的时候开辟空间。

当调用put方法存值时候,HashMap是允许键为null的,当键为null时因为无法计算Hash值,所以将键为null的键值对默认放入索引值为0的Entry对象中。首先遍历索引值为0的Entry对象,判断是否存在键为null的Entry对象,如果存在则用新的值覆盖旧值,并将旧值返回(put结束)。如果当前链中没有键为null的对象,则需要追加一个新的Entry对象。调用addEntry,首先判断当前map中的元素个数是否大于临界值,如果大于临界值并且当前需要追加的索引所对应的位置已经有Entry对象,为了避免链过长,则会触发扩容机制。如果当前数组已经达到最大值(Max)则直接扩容到Integer的最大值,否则扩大为原来的两倍。每次扩容时都是创建一个新的数组,然后底层通过C将旧数组中的数据复制到新创建的数组中。然后将新数组赋予成员变量。扩容结束之后,通过键计算hash值,如果键为null则hash为0,再通过Hash做位运算求出存放数据的索引值,位运算相当于是用hash相对于数组长度求模。根据计算出的索引值,将原Entry对象取出。创建新的Entry对象,将原对象放入到新对象的next属性中。再将新对象赋予数组(put结束)。当键不为空时计算键的hash值。然后判断是否存在,存在则覆盖,不存在则创建新的Entry对象追加到数组。追加前要判断是否需要扩容。原理和键为null时相同。

Hashtable

Hashtable和HashMap的底层数据结构相同,都是由Entry数组构成(数组+链表),数组默认长度是11,默认加载因子0.75f。它是线程安全的,因为所有的公共方法都有synchronized修饰,一个类中由synchronized修饰的所有方法同时只能有一个线程操作,所以HashTale可以保证每个人再操作数据时不受他人干扰,保证了数据的安全性,但是,会影响效率。

当向Hashtable插入键为null的值的时候,会抛空指针异常,即Hashtable中不允许有null的键存在。

Vector

数据结构是一个Object数组,这个数组的默认长度是10,可以通过有参构造方法创建不同长度的Vector集合。Vector集合每次默认扩容为原来的2倍。也可以通过两个参数的有参构造来设置扩容时的增量。当扩容之后的值大于Integer最大值-8时,扩容到Integer最大值。Vector也是线程安全的一个类,因为所有公共方法都有synchronized修饰。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值