HashMap随笔

一、hash

        即散列、任意长度-->hash算法-->固定长度、碰撞

        常用函数:直接取余、乘法取整、平方取中

        冲突处理:再散列法(rehash)、开放寻址法(增量)、拉链法(相同一链)

        应用:如MD5(不可逆推)

二、HashMap原理

        相较于数组、线性链表、二叉树,哈希表的性能是十分高的。哈希函数的设计好坏会直接影响到哈希表的优劣,好的哈希函数会尽可能地保证计算简单和散列地址分布均匀。

        HashMap为解决哈希冲突采用了链地址法,也就是数组+链表的方式,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的。从性能考虑,HashMap中的链表出现越少,性能才会越好。

        存储位置的确定流程是这样的:

        initialCapacity默认为16,扩容后新数组长度为之前的2倍,扩容相对来说是个耗资源的操作。

三、为何数组长度一定是2的次幂

        如果数组进行扩容,数组长度发生变化,而存储位置 index = h&(length-1),index也可能会发生变化,需要重新计算。数组长度保持2的次幂,length-1的低位都为1,会使得获得的数组索引index更加均匀,比如:

       上面的&运算,高位是不会对结果产生影响的(hash函数采用各种位运算可能也是为了使得低位更加散列),我们只关注低位bit,如果低位全部为1,那么对于h低位部分来说,任何一位的变化都会对结果产生影响,也就是说,要得到index=21这个存储位置,h的低位只有这一种组合。这也是数组长度设计为必须为2的次幂的原因。

        如果不是2的次幂,也就是低位不是全为1此时,要使得index=21,h的低位部分不再具有唯一性了,哈希冲突的几率会变的更大,同时,index对应的这个bit位无论如何不会等于1了,而对应的那些数组位置也就被白白浪费了。

四、重写equals方法需同时重写hashCode

        HashMap实现原理及源码分析 - dreamcatcher-cx - 博客园

五、JDK1.8红黑树

        JDK1.8以后 HashMap的数据结构发生了一些改变,从单纯的数组+链表结构变成数组+链表+红黑树。

你可能感兴趣的:(HashMap随笔)