【Java基础】Map相关面试问题

Map一定是面试官们最喜欢问的一个系列问题了

一般都会从最简单的开始问,如:Java容器类都有哪些,答:map,list等

再问那就说说map吧,map都分哪些种?答:hashMap,LinkedHashMap,TreeMap

问:哪些是有序的?答:hashMap是无序的,LinkedHashMap,TreeMap 是有序的

问:LinkedHashMap和TreeMap是怎么保证他们是有序的?

答:LinkedHashMap继承自HashMap内部维护了一个链表来保持它内部元素的插入顺序,迭代的时候也是按照插入的顺序迭代;TreeMap则是按照key的自然顺序来排序,如果需要可以继承Comparator接口来实现

问:说下HashMap的底层原理?

答:hashmap内部是一个数组+链表的数据结构,在put元素的时候,首先会把元素的key做hash运算,再通过这个hash值与数组长度做位运算,得到真正的元素下标,这时判断该下标是否有元素,如果有元素,则通过头插法将元素插入到链表。

get的时候就用相同的方法得到元素的下标,如果该数组下标只有一个元素,则该元素就是map的value,如果是链表结构,就循环链表得到map的value。

问:hashMap默认初始长度是多少?为什么这么规定?

答:16,为了服务于key映射到index的hash算法,该算法是用hash(key)&length-1,位运算可以保证性能,并且效果和取模一样,16-1是为了保证其二进制位数都是1,这样只要hash函数算出的结果是均匀的,得到的index也是均匀的

问:那hashMap是否是线程安全的?

答:非线程安全的,因为如果在高并发下,会导致在某个index下有循环链表的产生,这是如果get一个不存在的key,该key计算出的index值正好等于前面循环链表所在的index值,就会出现死循环,此处也可以通过讲解代码来详细说说怎么产生的循环链表

问:那如果构建一个线程安全的Map?

答:可以用hashTable和currentHashMap,HashTable就是实现了synchronize关键字的hashmap,效率很低,一般不建议使用,一般也很少有面试官问这块,可以就currentHashMap展开说说为什么currentHashMap是线程安全的。currentHashMap在Java7中是又若干个segment组成的,理论上可以支持最多segment数的并发,每个segment就相当于一个hashMap。

put的时候则由key得到hash值,由这个hash值定位到所在的segment,获得可重入锁,再通过hash值获取具体index,插入或者覆盖对象,释放锁

get的时候则由key得到hash值,由这个hash值定位到所在的segment,再定位到具体的index.

java8则改用synchronize和CAS来实现,同时底层改用链表+红黑树的结构,存放数据由hashEntry改为Node,并且由volatile关键字修饰value和next来保证其多线程下的可见性。

put的时候计算key的hash值,判断是否需要初始化,定位出的node如过为空,则利用CAS插入数据,如果hashCode==MOVIED==-1则扩容,否则利用synchronize锁写入数据。

get的时候依然通过hashcode寻址,如果是链表则按照链表方式寻址,如果是红黑树则按照红黑树方式寻址。

 

其实问题还有很多,也可以扩展:例如currentHashMap size()方法怎么保证他的线程安全?volatile关键字可以扩展谈谈,怎样判断一个链表是否有环?红黑树的具体实现,引申出其他各种树的相关知识等,篇幅有限先不一一说了,有机会再写

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