HashMap

  1. 与HashTable的区别

    非同步,可为null

  2. HashMap的性能影响因子

    初始容量(buckets的数量)和加载因子(扩容,时间和空间的计算)

  3. 同步方法

    Map m = Collections.synchronizedMap(new HashMap(...));
    
  4. HashMap为什么要使用数组+链表(大于8转成红黑树)

    基于时间和空间的考虑:

    • 时间:数组查询快,链表插入快
    • 空间:数组内存区域连续,指定大小,具有随机访问性;链表内存可以存在任何地方,每个数据都保存了下一个数据的内存地址(所以查找必须从第一个开始遍历,查找效率低)。
  5. HashMap7出现闭环的原因

    丢失和闭环均是由于改变链表方向导致的。

  6. HashMap的get

    1. 获得key的hash,然后根据hash和key按照插入时候的思路去查找get。
    2. 如果数据位置为null,则直接返回null。
    3. 如果数组位置不为null,则先看查找到的当前数组位置的数据的key与查找key是否一致。
    4. 如果不一致则进一步判断是否是红黑树类型,是的话则按照红黑树类型查找返回。
    5. 如果不是红黑树并且数据有next,则按照遍历链表的方式查找返回。
  7. HashMap的put

    1. 对数据进行hash值计算。
    2. 将数据插入前先检查当前table是否为空,如果为空则调用reSize方法进行初始化。
    3. 通过位运算获得key的目标位置,并判断当前位置情况。
    4. 如果当前位置为空则直接进行放置,如果跟当前key一致则进行覆盖。
    5. 如果当前有数据则看当前数据类型是否是红黑树,是的话需要调用putTreeVal。
    6. 如果不是红黑树则认为是个链表,然后再循环的查找进行尾部插入,同时还要考虑当前链表转红黑树。
    7. 对找到的旧节点进行判断,如果当前值为null,则直接替换。否则根据onlyIfAbsent是否为false判断是否进行替换。
    8. 以上步骤都进行完毕后对修改后的变量modCount加1,同时看最新的总结点。
  8. HashMap的resize

    1. 获得当前table数据,如果table当前数据足够大则不再进行扩容(MAXIMUM_CAPACITY),只调节阈值。
    2. 如果table当前数据扩容后的范围符合要求,则直接将容器大小跟阈值都扩容。
    3. 如果是带参构造函数则需要将阈值复制给容器容量。
    4. 否则认为该容器初始化未传参,需要初始化。
    5. 如果老table有数据则创建新容器并扩容,数据转移。
    6. 数据不为空的单独的节点直接重新hash分配新位置。
    7. 数据不为空,但是后面为链表的,则需要把链表数据进行区分来分开转移。
    8. 数据不为空,但是该节点是红黑树的,则调用spit。
  9. HashMap的remove

    查找table[i]是否存在,是否在首节点上,是否在红黑树上,是否在链表上,找到了则直接删除,同时注意平衡性。

  10. 7 VS 8

    1. 7中找Hash用了4次,8中只用了1次。
    2. 7 = 数组 + 链表,8 = 数组 + 链表 + 红黑树
    3. 7中是头插法,多线程容易造成环,8中是尾插法。
    4. 7的扩容是全部数据重新定位,8中是位置不变+ 移动旧size大小来实现更好些。
    5. 7是先判断是否要扩容再插入,8中是先插入再看是否要扩容。
    6. HashMap非线程安全。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值