1.ArrayList(a)和LinkedList(l)的区别与联系?
- 【底层】 a是数组,l是单链表(1.7前是循环链表)
- 【初始化】 a初始为0增加一个后变为10,也可指定长度<0会报异常,
l初始化 0每添加一个增加一个节点。 - 【增加删除】 a在长度不足时old+old>>1即1.5倍扩容,删除时数组不回缩, 通过Arrays.copy()复制。新增则添加一个节点,删除则链表中去掉该节点。
- 【用哪个】 数组是随机访问,链表是顺序访问。所以查找速度a>l。插入操作l找到找到位置后可以直接添加,a必须先将后面的后移。 添加操作a的开销在于扩容与复制,l的开销在于每次新增节点。在百万数据前l的效率要好。
- Vector的初始大小为10,如果没有指定每次增长的大小,则默认是翻倍增长
2.ArrayList和数组的区别。
- 数组定长,容器可以扩容
- a的底层是数组,数组可以存储基本类型,但是容器只能存储对象
- a可以存储异构对象,而数组只能存储相同数据类型的数据
3.collection与collections的区别
- Collection是集合类的一个顶级接口,其下直接继承的有List和Set
- Collections同Arrays类似,只不过时一个处理集合的工具类(sort, shuffling,max,min…)
4.容器的顶层接口是什么,Map是否继承了Collection
- 顶层接口是Collection,该接口实现了Iterable。
- Map是键值对的形式,并未继承Collection。
5.如果想得到一个线程安全的容器该怎么做
- 同步容器Vector HashTable是安全的。或者通过List list = Collections.synchronizedList(new ArrayList());该方法给返回线程安全的容器。
- 并发容器ConcurrentHashMap:(分段、CAS) CopyOnWriteArrayXXX(写时复制)ConcurrentSkipListMap(有排序功能)
6.HashMap和Hashtable的区别
- HashMap初始化容量1<<4(16),最大容量1<<30。扩容因子默认0.75f,超过8个会转成红黑树,小于6个会回退成链表。即使赋初值也会变成2的整数次幂,2倍扩容。键值可为空,线程不安全。重定义了hashcode使高16位也参与了运算 h = key.hashCode()) ^ (h >>> 16)
- Hashtable初始容量11,最大容量Integer.MAX_VALUE - 8。扩容因子0.75。可自定义容量,扩容因子。扩容方式(oldCapacity << 1) + 1。键值不可为空,线程安全。
7.为什么hashmap容量是2次幂
- (n - 1) & hash = hash % n &的速度更快 该方法保证了均匀散落。
8.ConcurrentHashMap了解吗
- 初始化大小0在添加第一个元素后为16,自定义则根据给定值,扩容因子,预计并发量计算得出。扩容方式为
- HashTable会通过synchronized给整个容器加锁,效率低下。ConcurrentHashMapjdk8之前采用分段锁技术8以后采用CAS操作。
9.CAS原理
- CAS(Compare And Swap)CAS有三个操作数,内存值V、预期值A、要修改的新值B,当且仅当A和V相等时才会将V修改为B,否则什么都不做。
- Java中CAS操作通过JNI本地方法实现,在JVM中程序会根据多处理器会给cmpxchg指令添加lock前缀。
10.哈希冲突的解决
开放定址法、再哈希法、链地址法、建立公共溢出区
11.快速失败和安全失败
- java.util 包的类都是快速失败的。java.util.concurrent 包的类是安全失败
- util包下的迭代器是直接对集合底层遍历,在遍历的过程中集合发生改变就会抛出ConcurrentModificationException异常。
- concurrent包下迭代器遍历的是复制后的数据,故不会抛出异常。
12.TreeMap了解吗
有排序的功能,底层红黑树,初始化长度为0