最近研究数据结构时想起一个有趣的底层问题:关于Linklist和ArrayList的性能问题。
考虑到Linklist的底层是链表结构实现,其存储时所使用的内存地址原理上是不必要连续的;而Arraylist是采用数组方式实现的,其存储时内存地址是连续的一块空间。此处比较性能是在存储的数据类型和数据量相同的情况下进行的比较。
/**
* 主要研究原因:操作系统对相邻的内存操作 用时几乎可以忽略
*
*
* 本类中的方法用来证明array 和linklist在查询和增加的时候实现的效率问题
* array 的查询速度比linklist要快,而且由于计算机对相邻的内存之间的存取比较快,
在对array进行插入时进行的元素移动操作要比对linklist进行查找操作用时要短,
所以相比之下array的性能更高
*
*/
public class Test_arrray_linklist {
public void test1() {
long[] l1 = new long[2];
long[] l2 = new long[2];
Integer[] ia = new Integer[5000];
for (int i = 0; i < 5000; i++) {
ia[i] = i;
}
int temp;
Random ran = new Random();
System.out.println("=================随机查取对比==========================");
List<Integer> list = new ArrayList<Integer>(Arrays.asList(ia));
l1[0] = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
temp = (Integer) list.get(ran.nextInt(5000));
}
l1[1] = System.currentTimeMillis();
long ltemp1 = l1[1] - l1[0];
System.out.println("array用时:" + ltemp1);
List<Integer> alist = new LinkedList<Integer>(Arrays.asList(ia));
l2[0] = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
temp = (Integer) alist.get(ran.nextInt(5000));
}
l2[1] = System.currentTimeMillis();
long ltemp2 = l2[1] - l2[0];
System.out.println("linklist用时:" + ltemp2);
System.out
.println("=================随机添加用时比较==========================");
l1[0] = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
list.add(ran.nextInt(5000), ran.nextInt(5000));
}
l1[1] = System.currentTimeMillis();
ltemp1 = l1[1] - l1[0];
System.out.println("array用时:" + ltemp1);
l2[0] = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
list.add(ran.nextInt(5000), ran.nextInt(5000));
}
l2[1] = System.currentTimeMillis();
ltemp2 = l2[1] - l2[0];
System.out.println("linklist用时:" + ltemp2);
System.out.println(ia.length);
}
public static void main(String[] args) {
Test_arrray_linklist tal = new Test_arrray_linklist();
tal.test1();
}
}
结论分析:由于CPU在执行的时候,对不相邻的内存地址需要不停的寻址,相对系统处理运算来说这占用了相当大的一部分时间。故造成ArrayList的性能更优(已系统内存足够为前提)。