HashMap面试问题整理

最近在看HashMap底层源码,看了很多小有收获,下面是针对一些HashMap相关面试总结的内容:

1.HashMap与HashTable的区别?

相同点:

  1.               HashMap和HashTable都是基于哈希表的数据结构
  2.              HashMap和HashTable都实现了Map和Serializable接口
  3.              元素类型都是key-value形式

不同点:

  1.             HashMap继承AbstratMap类;HashTable继承Dictionary类
  2.             HashMap允许key-value为空,HashTable不允许键值为空
  3.             HashMap进行put,get操作比HashTable效率高(HashTable对put,get加了同步锁)
  4.             HashMap是线程不安全的(1.7数据丢失、数据覆盖、死循环,1.8解决了数据丢失和死循环问题但还是会出现数据覆盖);HashTable是线程安全的
  5.             HashMap初始容量是16,扩容大小为2n;HashTable初始容量为11,扩容大小为2n+1

2.HashMap在JDK1.7与JDK1.8有什么区别?

  1.  JDK1.7是数组+单链表的数据机构;JDK1.8是数组+单链表+红黑树的数据结构(当数组的size大于64时且链表深度大于8时由链表转为红黑树,提高查询效率)
  2. jdk1.7采用头插法和jdk1.8采用尾插法(避免了出现死循环问题)
  3. jdk1.7和jdk1.8扩容方式不同

3.HashMap数组的容量为什么为2的n次幂

Hash存取高效必须使尽量减少碰撞、使数据均匀分布在数组中;

put操作时,需要将key的hash值与table-1做与运算来找到桶的下标位置,经过计算当数组长度为2的次幂时,数据在数组上分布比较均匀,从而使get操作更高效。

(为什么这样能均匀分布减少碰撞呢?2的n次方实际就是1后面n个0,2的n次方-1  实际就是n个1;
例如长度为9时候,3&(9-1)=0  2&(9-1)=0 ,都在0上,碰撞了;
例如长度为8时候,3&(8-1)=3  2&(8-1)=2 ,不同位置上,不碰撞;

4.jdk1.8为什么要用红黑树,为什么不直接使用链表?

红黑树的时间复杂度是O(logn),链表的时间复杂度是O(n);

树的节点是链表节点的两倍,当节点较少时,树占用内存较大,读写效率和链表相差不多;当节点较多时,链表的效率很低此时内存劣势可以忽略,此时采用红黑树来提高效率

5.HashMap解决线程不安全问题为什么不用HashTable而采用concurrentHashMap?

HashTable使用同步锁解决线程不安全问题,多个线程竞争一把锁,效率太低

concurrentHashMap采用锁分段技术,将数据分段存储加锁,减少了锁的碰撞几率,效率高

6.HashMap在JDK1.7是怎样造成死循环的?

多个线程同时进行put操作时,容易造成死循环

假设当前的表为 3->7-null,长度为2,扩容条件是1,即再put一个元素就需要扩容

线程一:执行到(Entry<K,V> next = e.next; )挂起此时,e=key(3) e.next=7

线程二:执行第一次 e=key(3) e.next=key(7);第二次:执行e=key(7) next=null ,第三次e=null结束,全部执行完毕链表为7->3->null

线程一解封,上次执行到e.next=key(7),继续执行,e=key(7),next=key(3) ;此时链表死循环3-7-3

7.HashMap造成数据覆盖过程?

线程a线程b同时做put操作,插入同一下标(源码中put操作,插入数据之前判断是否发生了碰撞,若没有则直接插入),通过hash碰撞校验后被挂起;此时线程B进行插入操作插入数据,线程a解除挂起后继续操作时会覆盖线程b的数据。

HashMap的扩容过程

当hashmap超过了负载因子定义的容量时,也就是map的容量大于本身的75%时,会进行扩容。

第一步:扩容,创建一个新的数组,长度为原数组的两倍

第二步;rehash,遍历原数组,把数据重新hash到新的数组中(需要重新hash是因为,变为新数组后hash规则发生了变化)

 hash公式:index = HashCode(Key) & (Length - 1)

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值