1. 程式人生 > >List介面(動態陣列)

List介面(動態陣列)

# List介面(動態陣列) List集合類中元素***有序且可重複*** ## ArrayList(重要) * 作為List介面的主要實現類 * 執行緒不安全的,效率高 * 底層使用Object[] elementData陣列儲存 ### ArrayList的原始碼分析 #### jdk7 1. 構造器 > ArrayList list = new ArrayList(); * 底層建立了長度為10的Object[]陣列elementData 2. 新增資料 >list.add(123) * 相當於elementData[0] = new Integer(123) * 底層的陣列長度為10,新增元素個數小於10時,正常新增元素 * 新增的元素個數大於10後(底層elementData陣列容量不夠),則需要擴容,預設擴容為原來容量的1.5倍(相當於新造一個數組,長度為原來長度的1.5倍)。同時需要將原來陣列的資料複製到新的陣列中 結論:建議使用帶參的構造器(避免在中間時擴容) > ArrayList list = new ArrayList(int capacity) #### jdk8 1. 構造器 > ArrayList list = new ArrayList(); * 底層Object[] elementData初始化為{},並沒有建立長度為10的陣列 2. 新增資料 >list.add(123) * 第一次add()時,底層才建立了長度為10的陣列,並將資料123新增到elementData[0]位置上 * 後續的新增與擴容操作與jdk7相同 #### 結論 * jdk7中的ArrayList的物件的建立類似於單例模式中的餓漢式 * jdk8中的ArrayList的物件的建立類似於單例模式中的懶漢式。延遲了陣列的建立,節省記憶體 ## LinkedList * 對於頻繁的插入、刪除操作,使用此類效率比ArrayList高 * 底層使用雙向連結串列儲存 ![](https://imgkr.cn-bj.ufileos.com/3b93e562-226f-46a5-be5f-a507f0e14123.png) ### LinkedList的原始碼分析 >LinkedList list = new LinkedList(); 內部聲明瞭Node型別的first和last屬性,預設值為null >list.add(123); 將123封裝到Node中,建立了Node物件 其中Node定義為(原始碼),體現了LinkedList雙向連結串列的特徵: ```java private static class Node { E item; LinkedList.Node next; LinkedList.Node prev; Node(LinkedList.Node prev, E element, LinkedList.Node next) { this.item = element; this.next = next; this.prev = prev; } } ``` ## Vector(不常用) * 作為List介面的古老實現類 * 執行緒安全的、效率低 * 底層使用Object[] elementData陣列儲存 ### Vector原始碼分析 * jdk7和jdk8中通過Vector()構造器建立物件時,底層都建立了長度為10的陣列 * 預設擴容為原來陣列長度的2倍 ## 三者異同 ### 相同點 三個類都實現了List介面,儲存資料的特點相同(有序、可重複的資料) ### 不同點 * 底層不同 * 不同情況下效率不同 * 執行緒安全問題 ## List介面中常用的方法 ***Collection中的方法都可用*** 1. add(int index , Object eles) 在index位置開始,將eles中的所有元素新增進來 ```java ArrayList list = new ArrayList(); list.add(123); list.add("Ann"); list.add(new Students("Tom",18,90)); list.add(987); list.add(3,"AA"); System.out.println(list);//[123, Ann, Students{name='Tom', age=18, grade=90.0}, AA, 987] ``` 2. addAll(int index , Collection eles) 從index位置開始將eles中的所有元素新增進來 ```java ArrayList list = new ArrayList(); list.add(123); list.add("Ann"); list.add(new Students("Tom",18,90)); list.add(987); ArrayList arrayList = new ArrayList(); arrayList.add(123); arrayList.add("Lisa"); list.addAll(arrayList); System.out.println(list);//[123, Ann, Students{name='Tom', age=18, grade=90.0}, 987, 123, Lisa] ``` 注意使用的是add()還是addAll(): * add()方法中將新增的元素看成一個整體,無論eles中有多少個元素,新增後的元素個數就是+1 * addAll()方法中eles中有多少個元素,新增後就多多少個元素 3. get(int index) 獲取指定index位置的元素 ```java System.out.println(list.get(1));//Ann ``` 4. indexOf(Object obj) 返回obj在當前集合中首次出現的位置 ```java System.out.println(list.indexOf(123));//0 ``` * 若存在該元素,返回其第一次出現的位置 * 若不存在該元素,返回-1 5. lastIndexOf(Object obj) 返回obj在當前集合中最後一次出現的位置 ```java System.out.println(list.lastIndexOf(123));//4 ``` * 若存在該元素,返回其最後一次出現的位置 * 若不存在該元素,返回-1 6. remove(int index) 移除指定index位置元素,並返回此元素 ```java System.out.println(list.remove(1));//Ann System.out.println(list);//[123, Students{name='Tom', age=18, grade=90.0}, 987, 123, Lisa] ``` 注意和Collection介面中的remove方法區分 7. set(int index , Object ele) 設定指定index位置的元素為ele ```java System.out.println(list);//[123, Students{name='Tom', age=18, grade=90.0}, 987, 123, Lisa] list.set(2,789); System.out.println(list);//[123, Students{name='Tom', age=18, grade=90.0}, 789, 123, Lisa] ``` 8. subList(int fromIndex , int toIndex) 返回從fromIndex到toIndex位置的子集合(左閉右開) ```java System.out.println(list);//[123, Students{name='Tom', age=18, grade=90.0}, 789, 123, Lisa] System.out.println(list.subList(1, 3));//[Students{name='Tom', age=18, grade=90.0}, 789] ``` ### 總結 * 增:add(Object obj) * 刪:remove(int index)、remove(Object obj) * 改:set(int index , Object obj) * 查:get(int index) * 插:add(int index , Object obj) * 長度:size() * 遍歷 ① Iterator迭代器方式 ②增強for迴圈 ③普通迴圈 ### 注:區分remove方法(形參) * List介面中remove方法要求裡面的形參是int型別 * Collection介面中remove方法要求裡面的形參是物件 * 若list中元素為1,2,3;remove(2)表明移除位置為2的元素;若想要移除元素2,需要remove(new Intege