问题
1 Arraylist和LinkedList的区别,它们是有序的还是无序的
2 ArrayList 和 LinkedList 的应用场景?
3.ArrayList的扩容机制说一下
****4.****HashMap实现原理介绍一下?
5.HashMap是线程安全的吗?
6.在 Java 的 hashmap 中 get一个元素的过程是怎样的?
7.hashmap的put过程介绍一下
8.HashMap的扩容机制介绍一下
9.ConcurrentHashMap怎么实现的?
10.说一下HashMap和Hashtable、ConcurrentMap的区别
11.Set集合有什么特点?如何实现key无重复的
回答
1
**底层数据结构不同:**ArrayList 是数组实现,LinkedList 是链表实现
**插入和删除操作的效率不同:**ArrayList 在尾部进行插入和删除操作时效率较高,在中间或开头插入、删除效率很低,需要移动后面的所有元素;
LinkedList 在头部和尾部进行插入、删除操作时效率很高,只需要调整节点的指针即可,
在中间位置操作,需要遍历链表找到目标位置,时间复杂度是 O (n),后续只需要调节指针
**随机访问的效率不同:**ArrayList 通过索引快速访问元素,时间复杂度为 O (1),LinkedList必须从头或尾逐个遍历查询,时间复杂度为O (n)
**空间占用:**LinkedList每个元素比ArrayList多两个指针,存储元素数量相同时,LinkedList占用更大
都是有序的
2
ArrayList适用于需要频繁访问的场景。LinkedList适用于频繁进行插入和删除操作的场景。
3.
ArrayList在添加元素时,如果当前元素个数已经达到了内部数组的容量上限,就会触发扩容操作。先算新容量,默认是原来的 1.5 倍,用移位运算效率更高;
扩容操作涉及创建新数组、复制旧元素、把引用指向新数组。
4.
JDK 7 是「数组 + 链表」 通过哈希算法将元素的键(Key)映射到数组中的槽位。采用头插法,多线程下会成环导致 get 死循环 
JDK 8 改成「数组 + 链表 + 红黑树」 ------链表长度 ≥ 8 且 数组长度 ≥ 64 时转红黑树,查找从 O(n) 降到 O(log n);树节点 ≤ 6 时退化回链表。采用尾插法,扩容按 hash & oldCap 拆成高低两条链整体搬走, 不会成环,但仍会覆盖丢数据

5.
JDK 8解决了 并发扩容时可能形成环形链表的问题,并没有解决多线程操作 HashMap 时的数据丢失问题
解决方法是 优先使用 ConcurrentHashMap
6.
get 就三步:
先 hash(key) 定位桶;桶空直接返回 null;
桶不空先比首节点(最快路径),命中就返回;没命中看类型------是树就走 getTreeNode 按 hash 分叉 O(log n),是链表就 do-while 逐个比 hash 和 equals,最长也就 8 个节点;找不到统一返回 null。全程不改 modCount,key 为 null 时 hash 是 0,落 0 号桶。
7.
put()方法用于向HashMap中添加键值对
1.拿到 key,计算它的 hash 值,通过 hash 值定位到数组对应的桶下标。
2.桶为空,创建一个新的 Node 对象来存储键值对
桶不为空,先判断头节点 key 是否一致,一致就覆盖 value。不一致就遍历链表或者红黑树,找到相同 key 就更新,找不到就插入新节点。
3.插入后如果链表长度到 8、数组≥64,链表转红黑树。
4.判断负载因子是否超过扩容阈值,超过就扩容为原来 2 倍,重新迁移节点。
8.
默认的负载因子是0.75,即如果hashmap中的元素个数超过了总容量75%,则会触发扩容
扩容做两件事 :新建 2 倍数组 → 搬移旧数据。
搬移的巧妙处 :因为容量是 2 的幂,(n-1) 的掩码扩容后高位只多 1 bit ,所以只需判断 e.hash & oldCap:为 0 留在原位,非 0 移到「原位 + oldCap」,无需重算 hash。
9.
JDK 1.7 :是Segment分段锁
JDK 8 :和 HashMap 一样的 数组 + 链表/红黑树 ,用 volatile+ CAS + synchronized 保证安全,锁粒度细化到单个桶 。
写入四步:
容器是否为空,为空则使用 volatile 加 CAS 来初始化
桶空用 CAS 无锁写入
桶非空 synchronized 锁住桶头节点再遍历覆盖/尾插
插入完成后更新计数。
读操作全程无锁 ------靠 volatile(Java 的关键字,用来修饰变量 ) 保证可见性,这是它读性能高的根本原因。
10.
HashMap:线程不安全,允许 null,初始容量 16,2 倍扩容,数组 + 链表 + 红黑树。 Hashtable:全局 synchronized 锁,并发差,不允许 null,初始容量 11,扩容 2n+1,只有数组 + 链表,基本淘汰。 ConcurrentHashMap:线程安全,不允许 null。1.7 分段锁;1.8 去掉分段锁,CAS + 桶级 synchronized,并发性能更好。
11.
set集合特点:Set集合中的元素是唯一的,不会出现重复的元素。
HashSet / LinkedHashSet :底层是哈希表,插入元素时先用 hashCode() 定位桶,再用 equals() 比较是否已存在相同元素,存在则不再插入;
TreeSet :底层是红黑树,插入元素时不调用 hashCode/equals,而是用自然排序或自定义 的返回值是否为 0 来判断是否重复。