目的
面试准备, 方便自己后续面试复习方便, 可能用不大, 这里做一个简单的个人学习记录.
资源
核心知识点
4个维度比较:
- 结构
- 随机访问速度
- 插入与删除
- CPU缓存, 局部性原理
结论:
- ArrayList
① 基于数组, 是联系的内存空间
②随机访问快(根据下标访问)
③尾部插入/删除性能可以, 其他部分插入/删除会涉及移动元素, 性能会降低
④可以利用CPU缓存, 局部性原理 - LinkedList
① 基于双向链表, 无需连续的内存
②随机访问慢(需要沿着链表去遍历)
③头尾插入删除性能高(中间插入可能还不如ArrayList, 主要时间浪费在找元素)
④占用内存多
自验证源码
测试随机访问
private static void randomAccess(List<Integer> list1, LinkedList<Integer> list2, int mid) {
StopWatch sw = new StopWatch("测试随机访问");
sw.start("测试随机访问: ArrayList");
list1.get(mid);
sw.stop();
sw.start("测试随机访问: LinkedList");
list2.get(mid);
sw.stop();
System.out.println(sw.prettyPrint());
}
结论: 随便访问 ArrayList 优秀, 直接通过下标获取, 而 LinkedList 需要遍历元素
StopWatch '测试随机访问': running time = 13501 ns
---------------------------------------------
ns % Task name
---------------------------------------------
000004000 030% 测试随机访问: ArrayList
000009501 070% 测试随机访问: LinkedList
测试头部插入
private static void addFirst(List<Integer> list1, LinkedList<Integer> list2) {
StopWatch sw = new StopWatch("测试头部插入");
sw.start("ArrayList: ");
list1.add(0, 100);
sw.stop();
sw.start("LinkedList: ");
list2.addFirst(100);
sw.stop();
System.out.println(sw.prettyPrint());
}
结论: 头部插入 LinkedList 性能好, 不用去移动元素.
StopWatch '测试头部插入': running time = 15301 ns
---------------------------------------------
ns % Task name
---------------------------------------------
000011301 074% ArrayList:
000004000 026% LinkedList:
测试中间插入
private static void addMiddle(List<Integer> list1, LinkedList<Integer> list2, int mid) {
StopWatch sw = new StopWatch("测试中间插入");
sw.start("ArrayList: ");
list1.add(mid, 100);
sw.stop();
sw.start("LinkedList: ");
list2.add(mid, 100);
sw.stop();
System.out.println(sw.prettyPrint());
}
结论: 一般 ArrayList 好一点, LinkedList 找元素会花费很多时间.
StopWatch '测试中间插入': running time = 10500 ns
---------------------------------------------
ns % Task name
---------------------------------------------
000001299 012% ArrayList:
000009201 088% LinkedList:
测试尾部插入
private static void addLast(List<Integer> list1, LinkedList<Integer> list2) {
StopWatch sw = new StopWatch("测试尾部插入");
sw.start("ArrayList: ");
list1.add(100);
sw.stop();
sw.start("LinkedList: ");
list2.add(100);
sw.stop();
System.out.println(sw.prettyPrint());
}
结论: 差不多.
StopWatch '测试尾部插入': running time = 3900 ns
---------------------------------------------
ns % Task name
---------------------------------------------
000002301 059% ArrayList:
000001599 041% LinkedList:
局部性原理, 空间占用测试
结论: LinkedList 更占空间.