HashMap回答知识点

面试官:了解HashMap实现原理吗?

先来的图吧 顺便加深集合框架知识体系 了解现在问在哪里
在这里插入图片描述

问:说下Hashmap的初始化过程
几个构造函数主要围绕两个参数进行
1 负载因子 控制扩容 缺省值0.75
2 容量:
a 构造函数的时候为了省空间 会先用threshold存一下 put的时候再重新设置threshold 缺省值16

	//构造方法
    public HashMap(int initialCapacity, float loadFactor) {
        ...
        this.loadFactor = loadFactor;
        this.threshold = tableSizeFor(initialCapacity);
    }

   //存放值时候初始化并resize
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
        ....
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
            ....
    }
 //resize 重新设置threshold 和cap
  final Node<K,V>[] resize() {
        Node<K,V>[] oldTab = table;
        int oldCap = (oldTab == null) ? 0 : oldTab.length;
        int oldThr = threshold;//这里
        int newCap, newThr = 0;
        if (oldCap > 0) {
           .....
        }
        else if (oldThr > 0)
            newCap = oldThr; //这里
        else {             
            newCap = DEFAULT_INITIAL_CAPACITY;//这里
            newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);//这里
        }

	
	b 初始化容量的时候 会自动调整成2的n次方 为了计算散列表位置需要使用位与2的n次幂-1(1111..)运算  保证每个下标都能命中。

问:了解hash怎么设计的吗 为什么这样? 为什么要与?
a:1.8 取key的hashcode 高低16位进行异或 然后和数组与
b: 使用2的n次幂做掩码 所以hashcode 只会在有较小的集合上产生影响 扩展高位上影响 又为了减少系统消耗使用异或方式 简单有效的避免冲突! 而且hash集合一般已经分布比较均匀 况且还有树来处理大量冲突
c:map容量不会有那莫大 2的31次方那么大

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

问:1.7 和1.8 hashmap的优化了什么 为什么

	    0:结构
		冲突解决方案里面增加了红黑树
		1:hash
			1.7 4次扰动  
			1.8 因为有红黑树解决冲突问题 扰动一次  
		2:put
		 由头插改成尾插
		  1.7头插法,单链表 当采用头插法就是能够提高插入的效率,但是也会容易出现逆序且环形链
          1.8尾插法 红黑树使用尾插法,能够避免出现逆序链表死循环的问题

		3:resize
		 扩容rehash过程省去 使用原hash值计算 扩容后 掩码只比以前扩了一位1  (如 0000 1111-》0001 1111) 
		 a在计算index的时候如果扩容未参与运算(判断方法 e.hash & oldCap  2的n次幂) 下标结果是一样的  index(原)=index(新) 
		 b如果参与与运算  也相当与 加上高位的值 就是扩容的值  index(原) = index(新)+扩容值
		 扩容顺序 由先扩容再插入 改为先插入后扩容 
		 a原因 没有了hash 添加之后再扩容更方便  不用预先hash 和equil判断
		 	

问:什么时候转红黑树?为什么? 冲突量降下来怎么办

a:在冲突必要严重的情况下 链表长度大于8 树形化结构还有个条件 map容量需要超过64
b:查找时间复杂度由O(n) 转为 O(logn)
hash设计合理的话 节点分布在hash桶中的频率遵循泊松分布 冲突8的情况很小
c:避免来回转换 数结构转链表阈值是6

问:hash冲突解决方式有哪些
1本文的链地址
2开放地址发 hash内加入一个探测量 冲突之后进行线性 二次 伪随机
3构造多个hash函数

问:put为什么改成尾插?除了尾插有没有其他解决方式?
a:头差法危害 引用倒转 多线程死循环
b1:环检测 差速遍历 有环肯定会相交
b2:借助额外缓存 每次判断已经遍历

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值