面试题 HashMap底层实现原理

  1. 用过HashMap吗? 什么是HashMap?
    HashMap实现了Map接口,Map接口对键值对进行映射。Map接口的两个基本实现是HashMap和TreeMap。TreeMap保证了对象的排列次序,而HashMap是无序的。HashMap的键和值可以赋值为null。HashMap是非synchronized的,可以通过Collections工具类的synchronizedMap方法使得HashMap是同步的。同步之后只允许一个线程访问对象。

  2. 知道HashMap的工作原理吗?
    HashMap是基于hash原理的。通过put()和get()方法获得和存储对象。当进行put()方法时,先通过key的hashCode()方法计算出hashCode,通过indexFor(hashCode,length)方法得到对象存储于table中的下标位置,也就是找到bucked的位置用来存储Entry。

  3. 知道HashMap中get()的工作原理吗?
    首先通过key的hashCode()方法的hashCode,通过hashCode找到对应的bucked的位置。通过keys.equals()方法找到正确的键值对,返回value的值。

  4. Hash算法的实现?还有哪些实现hash的方法?
    通过分析源码我们可知Hash算法的实现过程,简单来说这是一个“扰乱函数”,目的是让散列的分布更加均匀,减少碰撞。hash中存储着key的hashCode,把hash先右移16位,再与hash进行异或操作。简单的来说就是,高16bit不变,低16bit与高16bit进行异或操作。
    除留余数法、平方取中法、伪随机法。

  5. HashMap的数据结构是什么?
    JDK7中使用的是数组+链表的结构。JDK8中使用的是数组+链表+红黑树,在链表长度大于8时转为红黑树。
    数组的优点:易查找,不易进行增加修改操作。(通过下标查找)
    链表的优点:易进行增加修改,不易进行查找。(通过遍历查找)

  6. 说说对于HashMap扩容的理解。
    在addEntry()方法时会对阈值进行检测,当Entry的数量大于等于阈值。并且当前table位置上存在Entry。那么进行resize()。
    具体的resize()过程,遍历table重新进行散列。因为JDK7采用的是头插法,所以rehashing之后的链表是逆序的。

  7. 什么是HashSet?
    HashSet是Set接口的实现类,同样通过计算hashCode存储对象集合,它不允许集合中有重复的值。当我们使用HashSet存储对象时,首先要确保对象重写的equals()和hashCode()以免在集合中出现重复的对象。如果没有重写这两个方法,则使用默认的函数。
    HashSet通过add方法进行对象的添加。

  8. HashMap和HashSet的区别?
    HashMap存储的是键值对,HashSet存储的是对象。实现Map接口,实现Set接口。使用put()方法存储对象,使用add()方法存储对象。使用键对象来计算hashCode,使用成员对象来计算hasCode当hashCode相同时通过equals比较两个对象是否相等。

  9. 为什么桶容量为2的次幂?
    在通过indexFor()方法获得bucked位置时把hashCode和容量进行按位与计算。通过具体实例分析使用2的次幂进行计算时可以减少碰撞的发生,并且让散列尽可能的均匀分布。

  10. 在多线程环境下进行resize()会发生什么?
    会发生条件竞争。在进行扩容操作时通过hashcode找到bucked位置进行插入操作时因为采用的是头插法所以链表是逆序的。如果多个线程同时同时尝试调整大小,那么就发生了条件竞争,也就死循环了。HashMap不是线程安全的,不应再在HashMap中直接进行多线程的操作。

  11. 为什么使用String,Integer这样的wrapper类作为键对象更好?可以使用自定义类对象作为键对象吗?
    wrapper类具有两个特点,不可变性,并且重写了equals()和hashCode()。重写这两个方法可以使不同的key得到不同的hashCode,尽量的减少了碰撞,也就是提高了性能。不可变性在HashMap中是非常重要的。如果存入和获取时的hashCode不相同,那么就没办法找到正确的Entry对象了。不可变性还有保证线程安全的优点。
    自定义对象作为键对象时需要遵守equals()和hashCode()方法的定义规则。并且在插入集合之后就不可改变了。

  12. concurrenHashMap可以替代HashTable吗?
    HashMap和HashTable是基本等价的,区别在于前者是非synchronize的,而后者是synchronize的。所以前者性能更高。
    concurrentHashMap类是Java并发包中提供的一个线程安全且高效的HashMap实现类。
    而concurrentHashMap,相比于HashTable。前者的性能更高,而后者的安全性更强。在JDK7中concurrentHashMap采用的是分段锁的原理,在JDK8中采用的CAS + synchronized。HashTable采用的是synchronized原理

你可能感兴趣的:(Java,面试题)