结合实例看ArrayList和LinkedList区别

List集合的重要性不言而喻,直接开干。(下面测试基于openjdk1.8)

ArrayList: 底层采用的是数组,所以增删慢,查找快。

增删慢 : 比如你的数组里面现在有5个元素(对应下标是0-4),你现在需要往下标为2的地方添加元素,那么数组中下标为2,3,4的元素就需要往后移,但是如果你只是添加到数组末尾,是不用移动的(导致集合扩容除外);删除也一样,删除中间的就会导致后面的元素往前移。

查找快 :可以通过数组下标直接定位到元素(时间复杂度为O(1)).

遍历 :for循环遍历和iterator遍历时间复杂度都为O(n),但还是有区别的,如下:

		for (int i = 0; i < list.size(); i+=3) {//n 表示你要找几个元素
			list.get(i);
		}
		
		Iterator<Integer> iterator = list.iterator();
		while (iterator.hasNext()) {//n 表示list的长度
			iterator.next();
		}
LinkedList:底层采用的是链表,所以增删快

增删快:增删只需要移动链表的节点指针,查找慢
查找慢:从链表头开始挨着一个一个比对(时间复杂度为O(n)).
遍历:for循环遍历,时间复杂度为O(n^2);iterator遍历时间复杂度为O(n),如下:

		for (int i = 0; i < list.size(); i+=3) {
			list.get(i);//每一次get,都需要遍历一次链表
		}
		
		Iterator<Integer> iterator = list.iterator();
		while (iterator.hasNext()) {//只会遍历一次链表
			iterator.next();//每调用一次next,只是将遍历的指针往后面移一次
		}

ArrayList查找快 增删慢,LinkedList查找慢增删快.

下面大家思考这样一个问题:往集合插入10000个元素,然后再遍历出来,那个List更快?如果将数量增加到100000,又是那个List更快?
直接用代码证明:

public class TestList {
	public static void main(String[] args) {
		testArrayList(10000);
		System.out.println("=============================");
		testLinkedList(10000);
	}

	public static void testArrayList(int num) {
		long start = System.nanoTime();
		List<Integer> list = new ArrayList<Integer>();
		List<Integer> list2 = new ArrayList<Integer>();
		for (int i = 0; i < num; i++) {
			list.add(i);
		}
		long addEndTime = System.nanoTime();
		System.out.println("ArrayList insert spend time:" + (addEndTime - start) / 100);
		
		for (int i = 0; i < num; i++) {
			//每次都从中间添加新元素,这样后半部分的元素就需要往后移动
			//add(int index, Integer element)
			list2.add(i/2, i);
		}
		long addEndToTime = System.nanoTime();
		System.out.println("ArrayList insertTo spend time:" + (addEndToTime - addEndTime) / 100);
		
		for (int i = 0; i < list.size(); i++) {
			list.get(i);
		}
		long forEndTime = System.nanoTime();
		System.out.println("ArrayList foreach spend time:" + (forEndTime - addEndTime) / 100);
		Iterator<Integer> iterator = list.iterator();
		while (iterator.hasNext()) {
			iterator.next();
		}
		long end = System.nanoTime();
		System.out.println("ArrayList iterator spend time:" + (end - forEndTime) / 100);
	}

	public static void testLinkedList(int num) {
		long start = System.nanoTime();
		List<Integer> list = new LinkedList<Integer>();
		for (int i = 0; i < num; i++) {
			list.add(i);
		}
		long addEndTime = System.nanoTime();
		System.out.println("LinkedList insert spend time:" + (addEndTime - start) / 100);
		for (int i = 0; i < list.size(); i++) {
			list.get(i);
		}
		long forEndTime = System.nanoTime();
		System.out.println("LinkedList foreach spend time:" + (forEndTime - addEndTime) / 100);
		Iterator<Integer> iterator = list.iterator();
		while (iterator.hasNext()) {
			iterator.next();
		}
		long end = System.nanoTime();
		System.out.println("LinkedList iterator spend time:" + (end - forEndTime) / 100);
	}
}

上面的代码测试了往ArrayList和LinkedList中插入10000个元素,然后分别用for循环遍历和iterator遍历所花费的时间。看控制台打印:

ArrayList insert spend time:14534
ArrayList insertTo spend time:45437  ##新元素都从集合中间增加
ArrayList foreach spend time:55484
ArrayList iterator spend time:12512  ##遍历所有,iterator还是比foreach快
=============================
LinkedList insert spend time:15932
LinkedList foreach spend time:360552  ##linkedList用for循环遍历效率是真低呀
LinkedList iterator spend time:13550

下面看看数据量是100000的时候,所花费时间

ArrayList insert spend time:64547
ArrayList insertTo spend time:3093679
ArrayList foreach spend time:3127564
ArrayList iterator spend time:23360
=============================
LinkedList insert spend time:67861
LinkedList foreach spend time:33846313
LinkedList iterator spend time:24305

总结:

  • ArrayList如果每次都插入到集合末尾,插入效率和LinkedList差不多;如果ArrayLsit插入的位置随机,那么插入效率会比LinkedList差,当数据量变大时,差别会更明显。
  • ArrayList和LinkedList用****iterator遍历比for循环遍历快**(数据量很小时,比如几十,Arraylist用for或者iterator差别不大),当数据量大时,差距更明显;
  • 当数据量大时,最好不要用for循环遍历LinkedList.

下面贴出ArrayList -> add(int index, Integer element)方法源码:

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++;
    }
发布了42 篇原创文章 · 获赞 29 · 访问量 2527

猜你喜欢

转载自blog.csdn.net/qq_32314335/article/details/103777700