HashMap

HashMap

put流程

  1. HashMap是懒惰创建数组的,首次使用才创建数组

  2. 计算索引(桶下标)

  3. 如果桶下标还没有人占用,创建Node占位返回

  4. 如果桶下标已经有人占用

    如果是treeNode走红黑树的添加或更新逻辑

    如果是普通Node,走链表的添加或者跟新逻辑,如果链表长度超过树化阈值,一旦超过进行扩容

  5. 返回前检查容量是否超过阈值,一旦超过进行扩容

1.7和1.8区别

  1. 链表插入节点时,1.7是头插法,1.8是尾插法
  2. 1.7大于等于阈值且没有空位时才扩容,而1.8是大于阈值就扩容
  3. 1.8在扩容计算Node索引时,会优化

加载因子为何是0.75

  1. 空间占用和查询时间之间取得较好的平衡
  2. 大于这个值,空间节省了,但链表就会比较长影响性能
  3. 小于这个值,冲突减少了,但扩容就会更频繁,空间占用多

key能否为null,作为key的对象有什么要求

能,作为key必须重写hashCode和equals,并且key的内容不能修改

  1. HashMap底层是散列表/哈希表的数据结构

  2. HashMap是一个key-value的键值对的数据结构,从结构上来讲,jdk1.8之前是用数组+链表的方式实现,在jdk1.8之后加入了红黑树

  3. 哈希表是一个数组(在查询方面效率较高)和单向链表(在随机增删方面效率较高)的结合体

  4. map.put(k,v)

    map.get(k)

    map.put(k,v)实现原理

    第一步:先将(k,v)封装到Node对象中

    第二步:底层会调用HashCode()方法得出hash值,然后通过哈希函数/哈希算法,将hash值转换成数组的下标,下标位置上如果没有任何元素,就把Node添加到这个位置上。如果下标对应的位置上有链表,此时会拿着k和链表上每一节点中的k进行equals,如果所有equals方法返回都是false,那么这个新节点将被添加到链表末尾。如果其中有一个equals返回了true,那么这个节点的value将被覆盖

    map.get(k)实现原理

    第一步:先调用k的hashcode()方法得出哈希值,通过哈希算法转换成数组下标,通过数组下标快速定位到某个位置上,如果这个位置上什么都没有,返回null,如果这个位置上有单向链表,那么拿着参数k和单向链表上的每个节点中的k进行equals,如果所有equals方法返回false,那么get方法返回null,只要其中有一个节点的k和参数k equals的时候返回true,那么此时这个节点的value就是我们要找的value,get方法最终返回这个要找的value

    总结

    HashMap集合的key,会先后调用两个方法,一个方法是HashCode(),一个方法是equals(),那么这两个方法都需要重写

    为什么放在HashMap集合的key部分的元素需要重写equals方法呢?

    因为equals方法比较的是两个对象的内存地址

    HashMap集合的key部分特点

    无序不可重复

    为什么无序?因为不一定挂在哪个单向链表上

    不可重复怎么保证?equals方法来保证HashMap的key不可重复,如果key重复了,value会覆盖

  5. HashMap默认初始化容量为16,默认加载因子是0.75,这个加载因子是当hashmap集合底层数组的容量达到75%时,数组开始扩容

  6. 向Map集合中存取元素,都是先调用HashCode()方法,在调用equals方法。

    equals方法有可能调用,也有可能不调用

    拿put(k,v)/get(k)举例,什么时候equals不会调用?

    k.hashCode()方法返回哈希值,

    哈希值经过哈希算法转换成数组下标,

    数组下标位置上如果是null,equals不需要执行。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值