以前一直以为是linked中间插入和头部插入都是比arrayList快的,今天开会的时候谈到这个面试题,这里就重新认识一下这两个集合。
结论:不想存在性能瓶颈,不是一定要linkedlist的场景就使用arraylist就可以了,除了头插,arraylist基本都是优于linkedlist的
1.中间插入数据
linkedlist:
中间插入数据linkedlist是需要遍历移动和new node节点的
arraylist:
arraylist可能需要扩容和一定要移动数据的,但是arraylist使用的system.ArrayCopy进行扩容和移动数据是非常高效的,直接内存地址拷贝,然后赋值
移动数据:理解一下System.arraycopy(elementData, index, elementData, index + 1, size - index);
这行代码就会发现他只是将中间索引位置后面的数据直接copy到当前数组后一位的上
扩容:arraylist不一定需要扩容,每次扩容是原来的1.5倍,但是通过设置插入元素数,来保证他一定扩容进行测试,arraylist的速度还是更快。
public void add(int index, E element) {rangeCheckForAdd(index);ensureCapacityInternal(size + 1); // Increments modCount!!System.arraycopy(elementData, index, elementData, index + 1,size - index);elementData[index] = element;size++;}
测试程序
public void test_ArrayList() {ArrayList<Integer> list = new ArrayList<Integer>();long startTime = System.nanoTime();for (int i = 0; i < 106710; i++) {list.add( i);}System.out.println("初始化耗时:" + (System.nanoTime() - startTime));startTime = System.nanoTime();list.add(list.size() >> 1, 1);System.out.println("耗时:" + (System.nanoTime() - startTime));}@Testpublic void test_LinkedList() {LinkedList<Integer> list = new LinkedList<Integer>();long startTime = System.nanoTime();for (int i = 0; i < 106710; i++) {list.add(i);}System.out.println("初始化耗时:" + (System.nanoTime() - startTime));startTime = System.nanoTime();list.add(list.size() >> 1, 1);System.out.println("耗时:" + (System.nanoTime() - startTime));}
2.头插入
头插入linkedlist就比arraylist快很多了,即便是arraylist不需要扩容,也比不过linkedlist
因为linkedlist唯一耗时的地方就是new一个node节点
代码
@Testpublic void test_ArrayList_addCenter() {ArrayList<Integer> list = new ArrayList<Integer>();long startTime = System.nanoTime();for (int i = 0; i < 100000; i++) {list.add( i);}System.out.println("初始化耗时:" + (System.nanoTime() - startTime));startTime = System.nanoTime();
// list.add(list.size() >> 1, 1);list.add(0,1);System.out.println("耗时:" + (System.nanoTime() - startTime));}@Testpublic void test_LinkedList_addCenter() {LinkedList<Integer> list = new LinkedList<Integer>();long startTime = System.nanoTime();for (int i = 0; i < 100000; i++) {list.addFirst(i);}System.out.println("初始化耗时:" + (System.nanoTime() - startTime));startTime = System.nanoTime();
// list.add(list.size() >> 1, 1);list.add(1);System.out.println("耗时:" + (System.nanoTime() - startTime));}
3.尾插入
arraylist没扩容 基本持平,插入速度差不多,扩容的话linkedlist快一些
两组测试
3.1没扩容
@Testpublic void test_ArrayList_addCenter() {ArrayList<Integer> list = new ArrayList<Integer>();long startTime = System.nanoTime();for (int i = 0; i < 100000; i++) {list.add( i);}System.out.println("初始化耗时:" + (System.nanoTime() - startTime));startTime = System.nanoTime();
// list.add(list.size() >> 1, 1);list.add(1);System.out.println("耗时:" + (System.nanoTime() - startTime));}@Testpublic void test_LinkedList_addCenter() {LinkedList<Integer> list = new LinkedList<Integer>();long startTime = System.nanoTime();for (int i = 0; i < 100000; i++) {list.add(i);}System.out.println("初始化耗时:" + (System.nanoTime() - startTime));startTime = System.nanoTime();
// list.add(list.size() >> 1, 1);list.add(1);System.out.println("耗时:" + (System.nanoTime() - startTime));}
3.2进行扩容
@Testpublic void test_ArrayList_addCenter() {ArrayList<Integer> list = new ArrayList<Integer>();long startTime = System.nanoTime();for (int i = 0; i < 106710; i++) {list.add( i);}System.out.println("初始化耗时:" + (System.nanoTime() - startTime));startTime = System.nanoTime();
// list.add(list.size() >> 1, 1);list.add(1);System.out.println("耗时:" + (System.nanoTime() - startTime));}@Testpublic void test_LinkedList_addCenter() {LinkedList<Integer> list = new LinkedList<Integer>();long startTime = System.nanoTime();for (int i = 0; i < 106710; i++) {list.add(i);}System.out.println("初始化耗时:" + (System.nanoTime() - startTime));startTime = System.nanoTime();
// list.add(list.size() >> 1, 1);list.add(1);System.out.println("耗时:" + (System.nanoTime() - startTime));}