• [Java复习] 面试突击


    JDK 1.8 中hash算法和寻找算法是如何优化?

    // JDK 1.8以后的HashMap里面的一段源码

    static final int hash(Object key) {
            int h;
            return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

    高低16位参与运算:

    比如有一个key的hash值

    原值:        1111 1111 1111 1111     1111 1010 0111 1100

    右移16位:0000 0000 0000 0000  1111 1111 1111 1111

    异或运算: 1111 1111 1111 1111     0000 0101 1000 0011 -> 转换成int值表示hash值

    寻址算法优化:

    (n - 1) & hash  -> 算出数组里的一个位置下标

    取模运算性能差一些,为了优化数组寻址过程,数组长度2的n次方,hash & (n – 1)效果跟hash对n取模效果一样,与运算性能更高。

    核心在于低16的与运算

    hash算法的优化:对每个hash值,在他的低16位中,让高低16位进行了异或,让他的低16位同时保持了高低16位的特征,尽量避免一些hash值后续出现冲突,大家可能会进入数组的同一个位置。

    HashMap如何解决hash碰撞问题?

    hash冲突问题,链表+红黑树,O(n)和O(logn)

    map.put和map.get -> hash算法优化(避免hash冲突),寻址性能优化

    假设你的链表很长,可能会导致遍历链表,性能会比较差,O(n)

    优化,如果链表的长度达到了一定的长度之后,其实会把链表转换为红黑树,遍历一颗红黑树找一个元素,此时O(logn),性能会比链表高一些。

    说说HashMap是如何进行扩容的?

    2的N次方扩容。16,32,64。。。

    rehash:

    如果数组的长度扩容之后 = 32,重新对每个hash值进行寻址,也就是用每个hash值跟新数组的length - 1进行与操作。

    n-1          0000 0000 0000 0000  0000 0000 0001 1111

    hash1      1111 1111 1111 1111     0000 1111 0000 0101

    &结果      0000 0000 0000 0000  0000 0000 0000 0101 = 5(index = 5的位置)

    n-1          0000 0000 0000 0000 0000 0000 0001 1111

    hash2     1111 1111 1111 1111     0000 1111 0001 0101

    &结果    0000 0000 0000 0000   0000 0000 0001 0101 = 21(index = 21的位置)

    判断二进制结果中是否多出一个bit的1,如果没多,那么就是原来的index,如果多了出来,那么就是index + oldCap,通过这个方式,就避免了rehash的时候,用每个hash对新数组.length取模,取模性能不高,位运算的性能比较高。

    参考资料:

    互联网Java工程师面试突击(第三季)-- 中华石杉

  • 相关阅读:
    CF # 296 C Glass Carving (并查集 或者 multiset)
    linux 基本命令
    为什么是丰田——丰田的七个习惯之习惯一
    关注C-RAN 的五大理由
    一个效果非常华丽的仿桌面APP,却胜似Launcher
    IOS6.0自带下拉刷新控件UIRefreshControl
    POJ 2421--Constructing Roads【水题 && 最小生成树 && kruskal】
    ORACLE-017:SQL优化-is not null和nvl
    数据结构——栈
    数据结构——静态链表
  • 原文地址:https://www.cnblogs.com/fyql/p/12132477.html
Copyright © 2020-2023  润新知