1、简述LinkedHashMap
LinkedHashMap是HashMap的一个实现类,底层是数组+双向链表,与HashMap相比,LinkedHashMap可以保证元素的顺序,如插入顺序、访问顺序。下图为结构图:
public LinkedHashMap(int initialCapacity
, float loadFactor
, boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
上面为LinkedHashMap构造方法源码,其中,accessOrder=true代表访问顺序排序,accessOrder=false代表插入顺序排序(默认为false)。
2、为什么Hashtable的“t”不是大写
此类面试题一般很少问到,但由于好奇心驱使,便记录下来。
原因:Hashtable是在JDK1.0推出,而集合的统一命名规范(驼峰命名)是在JDK 2推出,Java为了兼容旧版本的JDK,于是一直保留Hashtable的命名方式,直到现在。
3、简述ConcurrentHashMap的数据结构
1)JDK1.7:ConcurrentHashMap采用分段锁(Segment)机制,底层是数组+链表的数据结构,即Segment数组 + HashEntry数组。
其中,Segment数组一共由16个Segment组成,每个Segment由多个HashEntry对象链接起来的链表,HashEntry 是用来封装映射表的键值对。每个Segment是一个可重入锁,多线程并发操作时,只锁住对应的Segment而不是整个Segment 数组,从而提升了并发性能。
2)JDK1.8:ConcurrentHashMap采用数组+链表+红黑树的数据结构,取消了Segment分段锁机制。内部通过灵活运用CAS + synchronized机制来保证线程安全的同时,也提升了性能。
4、WeakHashMap相关面试题
由于WeakHashMap平时面试问到较少,因此统一写在这里。
1)问题一:什么是WeakHashMap?
WeakHashMap是一种弱引用的Map,底层为数组 + 链表的数据结构。
2)问题二:WeakHashMap有什么用?
WeakHashMap适合作为缓存使用,它内部的key存储为弱引用,在GC时如果key不存在强引用的情况下会被回收掉,可以在一定程度上避免内存溢出。
3)问题三:什么情况下WeakHashMap会导致内存溢出?
当WeakHashMap中有大量的key都存在强引用,此时WeakHashMap基本退化为HashMap,此时WeakHashMap中的数据不会被回收,所以有可能会内存溢出。
4)问题四:WeakHashMap和HashMap的关系?
两者都实现了Map接口,WeakHashMap是弱引用实现,而HashMap是强引用实现,另外WeakHashMap是不能被克隆和序列化。
5、关于List的容量上限问题
1)ArrayList容量限制:
// ArrayList
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// Integer
@Native public static final int MAX_VALUE = 0x7fffffff;
上述源码可以看出,ArrayList最大容量是使用int类型的最大值,即2147483648,21亿多。
2)LinkedList容量限制:
从LinkedList构造方法源码可以看出,理论上LinkedList没有容量限制,可以无限存储,但是会收到内存大小的限制。
6、ArrayList是线程安全吗
这是一道老生常谈的问题了,ArrayList是线程不安全,源码注释明确说明它是线程不安全,如下图:
如remove方法,没有使用synchronized修饰,如果在多线程环境下同时操作,会出现安全问题。
7、简述常见的线程安全的List集合
1)Vector
2)SynchronizedList
3)CopyOnWriteArrayList
8、简述几种删除List元素的方式
1)使用Iterator迭代器遍历删除
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
for(Iterator<String> ite = list.iterator(); ite.hasNext();) {
String str = ite.next();
if(str.contains("a"))
ite.remove();
}
}
2)使用Stream删除
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
List<String> list2 = list.stream().filter(x ->
!x.contains("a")).collect(Collectors.toList());
}
9、简述几种List排序方式
1)直接使用集合自身的sort排序方法
2)使用工具类:Collections.sort()
3)将集合转成Stream流,再调用Stream自身的排序方法,比如:list.stream.sort()
10、List和Array之间如何转换
1)List转Array:使用List的toArray方法
2)Array转List:使用Arrays.asList(array)方法,此方法转出来的List不允许更改,如需要更改,可使用new ArrayList(Arrays.asList(array))
本篇面试题到此结束~