面试题总结——HashMap与ConcurrentHashMap
HashMap
1、
HashXXX(HashSet,HashMap)和TreeXXX(TreeSet,TreeMap)的区别?
①底层实现:HashXXX底层基于哈希表+红黑树;TreeXXX底层基于红黑树
②元素要求:HashXXX是无序存储,允许存放null(Set是key,Map是key+value);TreeXXX是有序存储(与比较器有关),不允许存放null(Set是key,Map是key+value)
③使用要求:使用HashXXX存储的类需要覆写hashCode()+equals();使用TreeXX需要实现Comparable接口或传入Comparator比较器
2、HashMap底层究竟是如何实现?
HashMap的底层:JDK1.8,HashMap采用位桶数组+链表+红黑树实现,HashMap采用懒加载
,当第一次put时才会初始化哈希表(resize()方法)。默认数组初始化长度为16(1<<4)。
HashMap的插入或更新
流程(put方法):当添加一个元素时,首先计算元素key的hash值,以此确定插入Entry数组中的位置(见下面对哈希函数的处理),若当前位置没有元素,就将key-value封装为Node(Map.Entry)放在该位置,若有元素(相同hash值),则遍历这个链表,看该链表中有没有哪个节点的key与当前key相同,若相同,则将该节点的key所对应的value修改为当前key所对应的value;若没有相同的,则将当前key-value所对应的结点插入到链表尾部。如果链表长度超过阈值(8),链表转换为红黑树。
HashMap的查找或删除
流程(get方法,remove方法):根据HashMap的哈希函数+(n-1)&hash,求得当前key所在数组中的位置,遍历该数组中的节点(无论是链表还是红黑树),寻找与key相同的结点,若存在,返回该结点中的value值或将该节点删除,若不存在,返回null。
3、HashMap到底是怎样确定当前元素在数组中的位置的?
首先根据HashMap中的hash()函数(h=key.hashCode())^ (h >>> 16):将key的hashCode的低16位和高16位做了个异或运算,确定当前key在HashMap中的hash值比较均匀。
再根据这个hash值确定对应数组位置:(n - 1) & hash,n代表HashMap数组的长度,由于HashMap数组的长度都是2的x次方,因此(n-1)&hash==hash%n,&运算