在專案中常常會用到Collection的ArrayList,LinkedList這兩種,這兩種在使用者或許沒有多大不同,但是在本質上卻有很大的不相同,今天來探討這兩者本質部份以及效能部分
1.ArrayList 資料結構
1.ArrayList 資料結構
3.1 比較兩者隨機查詢資料效能
import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Random; public class ListTest { //資料大小 int dataSize = 100000; // 紀錄開始時間 long[] testBeginTime = new long[4]; // 紀錄結束時間 long[] testEndTime = new long[4]; // 基本資料長度 Integer[] ia = new Integer[dataSize]; // 初始化隨機物件 Random random = new Random(); // 初始化ArrayList List<Integer> arraylist = null; // 初始化linkList List<Integer> linklist = null; { // 初始化ia陣列資料 for (int i = 0; i < ia.length; i++) { ia[i] = i; } arraylist = new ArrayList<Integer>(Arrays.asList(ia)); linklist = new LinkedList<Integer>(Arrays.asList(ia)); } void testListRandomQuery() { testBaginTime[0] = System.currentTimeMillis(); for (int i = 0; i < dataSize; i++) { arraylist.get(random.nextInt(dataSize)); } testEndTime[0] = System.currentTimeMillis(); testBaginTime[1] = System.currentTimeMillis(); for (int i = 0; i < dataSize; i++) { linklist.get(random.nextInt(dataSize)); } testEndTime[1] = System.currentTimeMillis(); System.out.println("ArrayList time : " + ((testEndTime[0] - testBeginTime[0]) / 1000) + " sec"); System.out.println("LinkedList time : " + ((testEndTime[1] - testBeginTime[1]) / 1000) + " sec"); }; void testListModify() { }; public static void main(String[] args) throws InterruptedException { new ListTest().testListRandomQuery(); } }
執行結果:
ArrayList time : 0 sec
LinkedList time : 7 sec
從執行結果來看,於讀取隨機資料LinkedList 所花的時間足足比ArrayList多花上七秒的時間
這是以十萬筆資料的情況來進行模擬,從這裡可以展現出ArrayList比LinkedList在進行隨機
讀取資料上效能的展現
3.2 比較兩者隨機插入資料效能
import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Random; public class ListTest { //資料大小 int dataSize = 100000; // 紀錄開始時間 long[] testBeginTime = new long[4]; // 紀錄結束時間 long[] testEndTime = new long[4]; // 基本資料長度 Integer[] ia = new Integer[dataSize]; // 初始化隨機物件 Random random = new Random(); // 初始化ArrayList List<Integer> arraylist = null; // 初始化linkList List<Integer> linklist = null; { // 初始化ia陣列資料 for (int i = 0; i < ia.length; i++) { ia[i] = i; } arraylist = new ArrayList<Integer>(Arrays.asList(ia)); linklist = new LinkedList<Integer>(Arrays.asList(ia)); } void testListModify() { testBaginTime[0] = System.currentTimeMillis(); for (int i = 0; i < dataSize; i++) { arraylist.add(random.nextInt(dataSize),i); } testEndTime[0] = System.currentTimeMillis(); testBaginTime[1] = System.currentTimeMillis(); for (int i = 0; i < dataSize; i++) { linklist.add(random.nextInt(dataSize),i); } testEndTime[1] = System.currentTimeMillis(); System.out.println("ArrayList time : " + ((testEndTime[0] - testBeginTime[0]) / 1000) + " sec"); System.out.println("LinkedList time : " + ((testEndTime[1] - testBeginTime[1]) / 1000) + " sec"); }; public static void main(String[] args) throws InterruptedException { new ListTest().testListModify(); } }
執行結果:
ArrayList time : 4 sec
LinkedList time : 128 sec
這個實驗數據很重要,因為常常看到網路上文章提到,LinkedList在進行插入動作時候效能
是優於ArrayList,但是實驗數據出來差異頗大。
3.3 比較兩者依序插入資料效能
import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Random; public class ListTest { //資料大小 int dataSize = 100000; // 紀錄開始時間 long[] testBaginTime = new long[4]; // 紀錄結束時間 long[] testEndTime = new long[4]; // 基本資料長度 Integer[] ia = new Integer[dataSize]; // 初始化隨機物件 Random random = new Random(); // 初始化ArrayList List<Integer> arraylist = null; // 初始化linkList List<Integer> linklist = null; { // 初始化ia陣列資料 for (int i = 0; i < ia.length; i++) { ia[i] = i; } arraylist = new ArrayList<Integer>(Arrays.asList(ia)); linklist = new LinkedList<Integer>(Arrays.asList(ia)); } void testListAdd() { testBaginTime[0] = System.currentTimeMillis(); for (int i = 0; i < dataSize; i++) { arraylist.add(i,random.nextInt(dataSize)); } testEndTime[0] = System.currentTimeMillis(); testBaginTime[1] = System.currentTimeMillis(); for (int i = 0; i < dataSize; i++) { linklist.add(i,random.nextInt(dataSize)); } testEndTime[1] = System.currentTimeMillis(); System.out.println("ArrayList time : " + ((testEndTime[0] - testBaginTime[0]) / 1000) + " sec"); System.out.println("LinkedList time : " + ((testEndTime[1] - testBaginTime[1]) / 1000) + " sec"); }; public static void main(String[] args) throws InterruptedException { new ListTest().testListAdd(); } }執行結果:
ArrayList time : 5 sec
LinkedList time : 44 sec
這個實驗數據很重要,因為常常看到網路上文章提到,LinkedList在進行插入動作時候效能 是優於ArrayList,但是實驗數據出來差異頗大。
3.4 比較兩者插入資料列首筆資料效能
//以上類別變數可參考上面測試範例 void testListHeadAdd(){ testBaginTime[0] = System.currentTimeMillis(); for (int i = 0; i < dataSize; i++) { arraylist.add(dataSize,random.nextInt(dataSize)); } testEndTime[0] = System.currentTimeMillis(); testBaginTime[1] = System.currentTimeMillis(); for (int i = 0; i < dataSize; i++) { linklist.add(dataSize,random.nextInt(dataSize)); } testEndTime[1] = System.currentTimeMillis(); System.out.println("ArrayList time : " + ((testEndTime[0] - testBaginTime[0]) / 1000) + " sec"); System.out.println("LinkedList time : " + ((testEndTime[1] - testBaginTime[1]) / 1000) + " sec"); }執行結果:
ArrayList time : 7 sec
LinkedList time : 0 sec
4 .結論:
- 讀取資料無論是隨機或是循序,使用優先順序為ArrayList > LinkedList
- 插入資料無論是危機或是循序,使用優先順序為ArrayList > LinkedList
5.個人看法:
從上面我所列出的資料結構圖形部分,基本的認知就是,當使用arraylist進行資料刪除候,就會產生"牽一髮動全身"的效應,所以感覺起來arraylist比較使用土方法在搬運資料。
而使用linkedlist進行資料刪除時候,只要記憶體指針指向另外一個地方,就完成了看起來很快。
但是無論使用哪一種的list,刪除元素都必須經過"找尋位置","執行搬運"這兩個動作,但很多時候大家都只看到了"執行搬運"這類的動作,但是缺忽略了"找尋位置"這類記憶體操作更是消耗時間,因此會有上面的測試程式這類的情形發生。
以上是我個人研究的淺見,歡迎大家互相討論。
以上是我個人研究的淺見,歡迎大家互相討論。
沒有留言:
不接受新意見。