零、重点
初始大小 | 加载因子 | 扩容大小 | 底层机制 | |
---|---|---|---|---|
ArrayList | 10 | 1(存满) | 1.5倍 | 动态数组,Arrays.copyof() |
HashMap | 16 | 0.75 | 2.0倍 | jdk1.7及其之前:数组+单向链表(有扩容死锁问题) jdk1.8及其之后:Node 数组 + 单向Node链表 + 红黑树 |
一、List
可插入重复元素。
结构 | 特点 | |
---|---|---|
ArrayList | 数组 | 查询快、增删慢,非同步 |
LinkedList | 链表 | 查询慢、增删快 |
Vector | 数组 | 同ArrayLis个,同步 |
二、Set
底层是Map,存储非重复元素,可存储null。
底层算法 | 特点 | |
HashSet | 哈希表 | 不保证顺序 |
LinkedHashSet | 哈希+链表 | 保证元素顺序(插入和取出顺序一致) |
TreeSet | 红黑树 | 不保证顺序,但对元素进行排序 |
三、Map
结构 | 有序性 | 可否为null | 查找效率 | |
HashMap | 数组+链表/红黑树 | 无序 | key和value都可为null | O(1) |
HashTable | 数组+链表 | 无序 | key和value都不可为null | O(n²) |
LinkedHashMap | 数组+双向链表 | 有序 | key和value都可为null | O(log(n)) |
TreeMap | 红黑树 | 有序 | key和value都可为null | O(log(n)) |
HashMap扩容原理:
(1)根据key的hash值求出存放的位置,如果数组为空则进行初始化;
(2)如果没有发生hash碰撞则直接放到hash表中,如果有碰撞且节点已存在则替换对应点节点;
(3)如果碰撞后hash表中存储的是链表或树状结构,则挂载到链表尾或树节点上;
(4)如果链表的长度超过了8,则会转化为红黑树;如果树节点个数少于6个时则会退化为链表。
问题:
(1)加载因子为什么是0.75?(为了减少rehash冲突使数据能够均匀的散列分布)
(2)jdk1.7多线程死锁问题如何解决的?(jdk1.8采用了高低位拆分转移的方式)
(3)HashMap扩容为什么是2的倍数?(高低位拆分,2倍减少了hash碰撞)