LinkedList与ArrayList二者性能简单PK
ArrayList与LinkedList
ArrayList底层是数组[],数字自带有索引下标,因此调用get()方法的时间复杂度为1;但是ArrayList在增删时除了定位到目标点以外,增加了元素或者删除了元素,都会对该目标节点后的元素产生影响,例如增加元素,那么长度变更,后续的所有元素都要向后挪一位,删除则是向前挪一位。
LinkedList底层是双向链表,链表嘛,查找时间复杂度近似O(n),毕竟要一个个查过去不是。但是增删只需要断开相邻的两个节点,然后插入或删去目标节点。
因此我们常常说,主查询使用ArrayList,频繁增删则使用LinkedList,但,为啥这个问题老是被问…为啥我工作里基本见不到LinkedList?最近准备面试看了下网上资料,部分博主贴出了代码演示,但是他们的删除操作,更多是删除固定位置,没有考虑到随机性。毕竟LinkedList增删元素时,如果都是很靠近首段和尾端,那么查找就不需要耗费那么多时间了,但恰恰查找元素才是LinkedList最耗费性能之处呀。
测试代码块
@Test
public void pkList() {
ArrayList<Integer> arrayList = new ArrayList<>();
LinkedList<Integer> linkedList = new LinkedList<>();
// 分别插入10w条数据至list集合
int length = 100000;
long start = System.currentTimeMillis();
for (int i = 0; i < length; i++) {
arrayList.add(i);
}
long end = System.currentTimeMillis();
System.out.println("arrayList插入10w条数据耗费时间为:" + (end - start) + "ms");
long start1 = System.currentTimeMillis();
for (int i = 0; i < length; i++) {
linkedList.add(i);
}
long end1 = System.currentTimeMillis();
System.out.println("linkedList插入10w条数据耗费时间为:" + (end1 - start1) + "ms");
// 1.直接删除,测试remove时长
int deleteLength = 1000;
long deleteStart = System.currentTimeMillis();
for (int i = 0; i < deleteLength; i++) {
arrayList.remove(i);
}
long deleteEnd = System.currentTimeMillis();
System.out.println("arrayList删除1000条数据耗费时间为:" + (deleteEnd - deleteStart) + "ms");
long deleteStart1 = System.currentTimeMillis();
for (int i = 0; i < deleteLength; i++) {
linkedList.remove(i);
}
long deleteEnd1 = System.currentTimeMillis();
System.out.println("linkedList删除1000条数据耗费时间为:" + (deleteEnd1 - deleteStart1) + "ms");
// 2.随机元素删除,测试remove时长
long deleteStart2 = System.currentTimeMillis();
for (int i = 0; i < deleteLength; i++) {
double random = Math.random();
double random1 = Math.random();
double index = (random * 1000 * random1 * 500) + 100;
arrayList.remove(index);
}
long deleteEnd2 = System.currentTimeMillis();
System.out.println("arrayList随机删除1000条数据耗费时间为:" + (deleteEnd2 - deleteStart2) + "ms");
long deleteStart3 = System.currentTimeMillis();
for (int i = 0; i < deleteLength; i++) {
double random = Math.random();
double random1 = Math.random();
double index = (random * 1000 * random1 * 500) + 100;
linkedList.remove(index);
}
long deleteEnd3 = System.currentTimeMillis();
System.out.println("linkedList随机删除1000条数据耗费时间为:" + (deleteEnd3 - deleteStart3) + "ms");
}
输出结果
arrayList插入10w条数据耗费时间为:11ms
linkedList插入10w条数据耗费时间为:7ms
arrayList删除1000条数据耗费时间为:33ms
linkedList删除1000条数据耗费时间为:2ms
arrayList随机删除1000条数据耗费时间为:121ms
linkedList随机删除1000条数据耗费时间为:235ms
总结
主查找ArrayList,增删频繁分情况:①如果List长度很短,小于1000,那么二者性能接近,图方便可以直接无脑ArrayList;②List长度很长,1w到100w条,增删都靠近首尾端,那么考虑性能采用LinkedList,如果位置非常随机,那么还是ArrayList好一些(我试了100w,随机删除范围扩大了一倍,ArrayList差不多是1.3s,LinkedList差不多4.9s,但是固定删除时,靠近首尾端,LinkedList耗时0-2ms,ArrayList耗时200-223ms);
一般情况下用ArrayList即可,除非考虑到接近首尾两端这个情况,不然几乎都是ArrayList;