Hashmap的使用

HashMap:
HashMap底层使用数组+链表+红黑树实现,默认初始化大小Defalut_capcity是1<<4, aka16这个值是写在源码上的,默认加载因子loadfactor 是0.75,默认树化因子是8,非数化因子是6,这是HashMap的基本参数。
当我们放置元素到HashMap中,创建的HashMap底层数组在一开始是没有初始化的,通过hash()这个方法,算出来目标hash值后,放置这个内容到数组中,但是数组当前没有初始化,所以调用resize方法来初始化数组,初始化后,在放置内容时,直接调用newNode方法来将数据放置在数组的桶中。
当元素发生Hash碰撞,HashMap使用拉链法来解决,将碰撞的元素,插在之前桶中的最后一个元素的后面。这样就形成了链表。
当单个链表的元素个数超过8时,可能会发生树化过程。这个过程不一定发生,因为如果当前数组的长度没有到64(HashMap定义的最小书画长度)那么就会先扩容数组,当扩容数组的时候,会产生rehash过程,可能就降低了链表的长度,也就使长度不到8了。但是如果当前数组长度已经达到64,那么就会将当前链表进化成红黑树。
扩容还会发生在hashmap中的元素个数大于当前数组长度的0.75倍时,也就是说,当前数组长度如果是16,那么如果元素个数大于12,就会发生扩容,扩容过程是扩容到原来的两倍,因为默认大小一定是2的幂次方,所以扩容后也是2的幂次方

扩容时发生的Rehash,会改变以一次的threhold,也是翻倍过程,为什么这里使用2的幂次方,是因为好在rehash过程中计算当前链表中的数据在扩容后的位置。因为这个使用,这个数据只能放置在两个地方,要不是原来的位置,要不是扩容后的位置,扩容后的位置是原来的位置加上原来的数组长度。

******************************************************别人不问就不说********************************
1.7和1.8的区别:
1.7没有红黑树过程,且采用头插法。
红黑树解决了HashMap链表定位时间过长的问题,原来如果一个链表假说有32个元素,那么最次的定位时长是32次遍历。时间很慢,但是1.8使用红黑树以后,会发现这个时候,无论如何定为次数不会超过5

头插法,头插法其实是比尾插法快的,是更加节省效率的,但是1.8还是使用了尾插法,是因为第一:节省的效率有限,一个红黑树能节省的效率就已经远远超过头插和尾插的区别了,第二也是最关键的原因,头插法在多线程操作的时候,可能会形成链表环,使得获取数据时进入死循环,虽然我们不建议在多线程场景下使用HashMap但是不可避免的是这个场景还是会出现在开发过程中,所以1.8改成了尾插法。

hashmap底层原理是HashMap基于hashing原理,通过put和get方法储存和获取对象。当将键值对传递给put方法时,它调用键对象的hashCode方法来计算hashcode,然后找到bucket位置来储存值对象。当获取对象时,通过键对象的equals方法找到正确的键值对,然后返回值对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会储存在链表的下一个节点中。HashMap在每个链表节点中储存键值对对象。

HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。

 简单来说,HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。
重写equals方法需同时重写hashCode方法.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值