• Java面经之:HashMap


    1、java1.7 Hashmap默认的初始容量为什么是2的幂?

      

      hashsize初始是大小是16.

      hash为计算后的hash值

      hash&(length-1) 按位与

      2n次方-1  这个数的二进制由1组成,比如16是10000,减1过后就是1111,全是1 相与,这样的好处是降低hash冲突,降低空间浪费 。

            才能拿到为1的数, 

      (1)先拿到hash值,hash值会大于hashmapsize,所以再用indexfor来找到数组下标,通常是取余,但是根据效率是通过hash*&(leng-1)原理如上图。

       相与的时候:快速拿到数组下标,并且是均匀分布。

    hash

    resize扩容, 自动扩容

      transfer  while遍历旧的值重新rehash新的值,到新的表中

    Java 7非常容易碰到死锁

    1、  java7是头插法, 

    2、 潜在的安全问题。  

    java1.8

    1、数组+链表/红黑树

    2、扩容时插入顺序 的改进

    3、函数方法

      1、foreach

      2、compute系列

    4、Map的新api

      1、merge

      2、replace

    put

      1、找到了这个元素,hash表中是空的,直接放入

      2、树节点,放入红黑树

      3、放入链表,链表判断是否会变为红黑树。

    1、HashMap线程不安全原因:
    原因:
    JDK1.7 中,由于多线程对HashMap进行扩容,调用了HashMap#transfer(),具体原因:某个线程执行过程中,被挂起,其他线程已经完成数据迁移,等CPU资源释放后被挂起的线程重新执行之前的逻辑,数据已经被改变,造成死循环、数据丢失。
    JDK1.8 中,由于多线程对HashMap进行put操作,调用了HashMap#putVal(),具体原因:假设两个线程A、B都在进行put操作,并且hash函数计算出的插入下标是相同的,当线程A执行完第六行代码后由于时间片耗尽导致被挂起,而线程B得到时间片后在该下标处插入了元素,完成了正常的插入,然后线程A获得时间片,由于之前已经进行了hash碰撞的判断,所有此时不会再进行判断,而是直接进行插入,这就导致了线程B插入的数据被线程A覆盖了,从而线程不安全。
     

  • 相关阅读:
    oracle 存储过程的基本语法
    Silverlight :服务器返回错误: NotFound 错误
    利用CSS定位背景图片 backgroundposition
    解决 asp.net 伪静态 IIS设置后 直正HTML无法显示的问题
    输入框下拉列表提示
    同步文本框内容的JS代码
    判断文本框只能输入中文汉字的代码
    如何解决padding标记在ie7、ie6以及firefox中的兼容问题
    ASP.NET用URLRewriter.dll实现伪静态
    滑动效果,适合做faq或menu
  • 原文地址:https://www.cnblogs.com/Alei777/p/16086428.html
Copyright © 2020-2023  润新知