1. Arraylist 与 LinkedList 异同
1. 是否线程安全: 都不能保证线程安全
2. 底层数据结构: 一个是数组,一个是双向循环链表
3. 插入和删除是否受位置影响:
4. 是否支持快速随机访问: array支持
5. 内存空间占用: ArrayList的空间浪费主要是结尾要预留一定空间,LinkedList的空间花费是每个元素多要保存后继、前驱和数据
使用场景:
1、如果对各个索引元素进行大量的存储或删除操作,ArrayList要优于LinkedList
2、如果主要对列表进行循环,并且循环时进入插入或者删除操作,LinkedList要优于ArrayList
2. ArrayList 与 Vector 区别
都是List的实现类,底层用Object[]实现, vector是线程安全的
3. HashMap的底层实现
jdk1.8之前
JDK1.8之前是数组➕链表实现,链表主要是解决哈希冲突。如果定位到的数据位置,不含有链表,那么查找、添加等操作很快,O(1);如果含有链表,对于添加操作,O(1)只需要把元素放到链表头部,查找的时候遍历链表,通过key对象的equals方法注意对比查找。
jdk1.8以后
主要是解决冲突发生变化,当链表长度大于阈值(默认8),将链表转化为红黑树,减少搜索时间。
4. HashMap和Hashtable的区别
- 线程安全: HashMap不是线程安全的,Hashtable是线程安全的,用synchronized修饰
- 效率: HashMap效率更高,Hashtable基本被淘汰,很少使用了
- 对于NullKey和NullValue: HashMap支持一个NulKey,多个NullValue,Hashtable不允许
- 初始化量的大小和每次扩容量的大小: ①创建时如果不指定容量初始值,Hashtable 默认的初始大小为11,之后每次扩充,容量变为原来的2n+1。HashMap 默认的初始化大小为16。之后每次扩充,容量变为原来的2倍。②创建时如果给定了容量初始值,那么 Hashtable 会直接使用你给定的大小,而 HashMap 会将其扩充为2的幂次方大小。
- 底层数据结构: 超过阈值转化为红黑树
5. HashMap的长度为什么是2的幂次方
尽量把数据分配均匀,存取高效 。这个实现就是把数据存储到哪个链表/红黑树的算法。
我们首先可能会想到采用%取余的操作来实现。但是,重点来了: “取余(%)操作中如果除数是2的幂次则等价于与其除数减一的与(&)操作(也就是说 hash%length==hash&(length-1)的前提是 length 是2的 n 次方;)。” 并且 采用二进制位操作 &,相对于%能够提高运算效率,这就解释了 HashMap 的长度为什么是2的幂次方
6. HashSet 和 HashMap 区别
实现上: 一个实现了Set 一个实现Map
功能上:HashMap是key-value,HashSet支持对象
hashcode: HashMap使用key计算HashCode,HashSet使用对象计算hashcode,对于两个对象来说,hashcode可能相同,就用equals方法判断相等性。如果两个对象不同的话,那么返回false。
速度效率: HashMap更快
7. ConcurrentHashMap 和 Hashtable 的区别
底层数据结构:JDK1.8之后ConcurrentHashMap和HashMap的结构一样,也会升级红黑树。而Hashtable是数据+链表。
线程安全: Hashtable是全表锁。
8. ConcurrentHashMap线程安全的具体实现方式/底层具体实现
JDK1.8以前
数据分为一段一段的存储,然后每一段数据加一把锁,
JDK1.8之后
取消了Segment分段锁,采用CAS和synchronized来保证并发安全。数据结构跟HashMap1.8的结构类似,数组+链表/红黑二叉树
9. 集合框架底层数据结构总结
10、Object中的hashcode和equals问题
重写equals时为什么要重写hashcode