千万不要再回答简单的ArrayList查询快,LinkedList插入快了,这样回答一看就是背题的…
先上结论
ArrayList
- 基于数组,需要分配连续内存
- 随机访问快(根据下表访问)
- 尾部插入、删除性能可能,其他部分插入、删除会移动数据,性能会降低
- 可以利用cpu缓存,局部性原理
LinkedList
- 基于双向链表,无需连续内存
- 随机访问慢(需要沿着链表遍历)
- 头尾插入删除性能高
- 占用内存多
原理
首先呢,感慨一句,真的随着年限的增长,越来越觉得世界是相通的,技术也是相通的,如果你明白计算机原理,再回头来看JAVA的很多知识,就自然而然的明白了。
先说CPU缓存
为什么arraylist可以利用,而linkedlist不可以呢?
先看看arraylist的基本结构,如果我这次拿到了3,2、4就可以被认为是有可能被访问到的资源,就有可能把2、3、4都放进cpu缓存。说到这多提一嘴,cpu缓存是比内存快的多的,这就是计算机原理中的知识了,大家先知道这个就可以。
而linkedlist呢?他的内存结构是不连续的,这次我拿到了2,我拿他两遍的值有用吗?没用对吧,所以linkedlit无法利用cpu缓存。
再说头尾删除插入
linkedlist快,无需多说吧?无非就是换个指针地址就ok了。而arraylist为什么尾部快,其他位置慢呢?一个图就明白
如果删除尾部,直接拿掉就完事了,很快的。
但是我如果删掉头部呢?则需要整体都移动过去,是不是就慢了呢?
不停的插入,linkedlist比arraylist快吗?
不一定,真的不一定,arraylist扩容是会影响效率,如果我给定义了范围呢?
public static void main(String[] args) {
List<Integer> arraylist = new ArrayList<>(1000000);
List<Integer> linklist = new LinkedList<>();
long astart = System.currentTimeMillis();
for (int i =0; i< 1000000; i++){
arraylist.add(i);
}
long aend = System.currentTimeMillis();
long lstart = System.currentTimeMillis();
for (int i =0; i< 1000000; i++){
linklist.add(i);
}
long lend = System.currentTimeMillis();
System.out.println("arraylist:" + (aend - astart) );
System.out.println("linklist:" + (lend - lstart) );
}
大家可以执行代码试试看咯,这是我自己测试的三次结果,这个问题该怎么回答不言而喻了吧?
arraylist:14
linklist:140
arraylist:16
linklist:153
arraylist:20
linklist:145
PS
虽然查询速度是他们的一个区别,但是其实更像是矬子里拔将军,实际他们都不适合于做查询,只是考虑查询速度,HashMap不香么?