結合實例看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++;
    }
發佈了51 篇原創文章 · 獲贊 41 · 訪問量 4925
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章