arrayList
arrayList初始化的时候,如果是无参构造器,初始容量是0,如果有参构造初始容量为该参数大小,在无参构造的时候,当add添加元素时,会自动扩容为10,然后继续继续添加直到超过10的时候,会发生扩容,扩容为当前1.5倍,即当前容量+当前容量>>>1。如果按照addAll();进行添加元素的时候,会和自动扩容进行比较,哪个大 就选择哪个为当前list的容量。
2.iterator的fail-fast 和fail-safe
ArrayList是fail-fast的典型代表,遍历的同时不能修改,尽快失败退出。
fail-fast遍历前,先记录当前list的修改次数mod-count,然后每次遍历都会判断mod-count是否等于当前expectModCount,如果不等,就抛异常。
CopyOnWriteArrayList是fail-safe的典型代表。遍历同时可以修改数据,原理是读写分离
fail-safe遍历前,先把集合中的元素copy到snapshot[]数组中,然后遍历snapshot数组内的元素,就算修改list内数据,也不会影响修改前的遍历结果。
3.LinkedList和ArrayList比较
1.arrayList
基于数组实现,需要连续内存
随机访问快(根据下标访问)
尾部插入,删除性能可以,单是其他部分插入、删除都会移动数据,性能较低
可以利用cpu缓存,局部性原理
2.LingkedList
基于双向链表,无需连续内存。
随机访问慢(需要遍历整个链表)
头尾插入性能高
占用内存多
HashMap
底层数据结构,1.7和1.8有何不同?
1.7底层是数组+链表,而1.8底层是数组+(链表|红黑树)
在1.8的HashMap中,初始容量是16,扩容因子是0.75,当map中值超过容量*扩容因子,会二倍扩容,直到容量为64时,停止扩容。当总容量=64,且链表长度大于8时才会转换成红黑树。
为什么要用红黑树?
因为如果链表太长,会导致性能下降。
何时会树化?
当链表长度大于树化阈值8,且数组长度
为何不直接用树,而是先用链表?
因为树treenode内存占用逼链表node大,非必要不会转化成树。
用质数可以分布更均匀,用2的n次幂性能高,但是空间差。