標籤:java集合架構 list介面 list集合 arraylist類 linkedlist類 java免費教程
集合架構
在數組的使用過程中可以看到,想要向數組中插入元素和刪除元素非常麻煩,而且數組的長度是無法改變的。java為我們提供了批量儲存資料更加方便的容器,就是集合。
集合和數組的作用一樣,都是為了使用一個變數來儲存一批資料的;但集合使用起來更加方便,而且集合的長度是可以變化的。
List介面
List集合可以儲存有序的,可重複的資料;
常用的子類是ArrayList和LinkedList兩個類
ArrayList類
這是一個底層由數組實現的集合類,是對數組進行了封裝。
執行個體:package collection.list.arrayList;import java.util.ArrayList;/** * ArrayListDemo類 * 示範ArrayList類中常用方法的使用 * @author 學霸聯盟 - 趙燦 */public class ArrayListDemo {public static void main(String[] args) {//當建立ArrayList對象時,底層會建立一個空的Object類型的數組ArrayList arrayList = new ArrayList();//迴圈存入資料for (int element = 1; element <= 11; element++) {/* * 通過arrayList的add方法向集合中添加資料 * 任何類型的資料都會被轉換成Object類型加入集合 * 當加入集合的資料為基礎資料型別 (Elementary Data Type)的資料時 * 會先將基礎資料型別 (Elementary Data Type)的資料轉換成對應的封裝類類型 * 例如:int類型的資料會先轉換成Integer類型 * 然後再將Integer類型轉換成Object類型 * 從基礎資料型別 (Elementary Data Type)轉換成封裝類類型的過程叫做自動裝箱 * 這個轉換過程由系統自動處理完成 * * 添加第一個資料時,底層會重新建立長度為10的Object類型的數組 * 這裡的10一般認為是ArrayList集合的初始長度 * 並把第一個資料存放區到底層Object類型數組下標為0的位置上; * 當底層數組存滿後,再向集合中添加元素時, * 底層會建立一個長度為原數組長度1.5倍的新數組 * 這裡的1.5叫做集合的增長因子 * 並將原數組中的所有元素複製到新數組中 * 然後在新數組下標為原數組長度的位置上新增當前元素 * * 例如:本例中第一次增長在存入第11個元素時,即element==11時 * 此時原數組的長度為10(最大下標為9) * 底層會建立長度為15(10的1.5倍)的Object類型的數組 * 然後將原數組中所有資料複製到新數組中 * 然後在新數組下標為10的位置上存入元素11 * 注意:這裡的element不是集合的下標,而是存入集合的元素(資料) * 理論最大儲存元素個數為int類型的最大值2147483647 [0x7fffffff] */arrayList.add(element);}/* * 迴圈取出資料 * 這裡的index代表集合的下標 * 集合的長度使用size方法擷取,而不是length屬性,也不是length方法 * 擷取數組長度使用的length屬性 * 擷取String長度使用的是length方法 */for (int index = 0; index < arrayList.size(); index++) {// 使用get方法擷取集合中的資料,擷取出來的資料類型為ObjectObject element = arrayList.get(index);// 強制類型轉換Integer data = (Integer)element;/* * Integer是參考型別 * 那麼問題來了,基礎資料型別 (Elementary Data Type)的變數e為什麼可以賦參考型別的值呢? * 因為Integer是int的封裝類 * 從封裝類型轉換成基礎資料型別 (Elementary Data Type)的過程,叫做自動拆箱 * 這個轉換過程也由系統自動處理完成 */int e = data;//每次迴圈均輸出變數e的值和兩個空格System.out.print(e + " ");}}}運行結果:1 2 3 4 5 6 7 8 9 10 11小結:
1、集合的初始長度為10,增長因子為1.5
2、理論最大儲存長度為int類型的最大值2147483647 [0x7fffffff]
3、存入基礎資料型別 (Elementary Data Type)資料時存在自動裝箱
4、未使用泛型時,取出資料的資料類型是Object
5、擷取集合長度使用size方法
6、通過結果可以看到,取出的順序和存入的順序是一致的,所以它是有序的集合
7、底層由數組實現,其記憶體空間是連續的,所以查詢元素速度較快
8、插入和刪除速度較慢,因為要將插入位置之後的元素依次後移,刪除位元置之後的元素依次前移
執行個體:示範ArrayList類中的常用方法的使用package collection.list.arrayList;import java.util.ArrayList;import java.util.Arrays;/** * ArrayListDemo類 * 示範ArrayList類中常用方法的使用 * @author 學霸聯盟 - 趙燦 */public class ArrayListDemo2 {public static void main(String[] args) {//建立ArrayList對象ArrayList arrayList1 = new ArrayList();ArrayList arrayList2 = new ArrayList();//迴圈存入資料for (int element = 1; element <= 3; element++) {//迴圈結束後兩個集合中都有1,2,3三個元素arrayList1.add(element);arrayList2.add(element);}//遍曆集合;運行結果:1 2 3ergodicArrayList(arrayList1);/* * 插入資料,向集合下標為1的位置,插入資料10 * 插入的下標值必須小於等於集合長度 * 即:插入下標<=集合.size(); * 如果插入下標大於集合長度的位置,會出現IndexOutOfBoundsException */arrayList1.add(1,10);//遍曆插入資料後的集合;運行結果:1 10 2 3ergodicArrayList(arrayList1);//依次向集合arrayList1中加入arrayList2集合中的每個元素arrayList1.addAll(arrayList2);//遍曆插入資料後的集合;運行結果:1 10 2 3 1 2 3ergodicArrayList(arrayList1);//contains方法,判斷集合中是否包含某個元素boolean isContains = arrayList1.contains(10);//輸出結果:集合arrayList1是否包含10:trueSystem.out.println("集合arrayList1是否包含10:" + isContains);//輸出結果:集合arrayList1是否包含11:falseSystem.out.println("集合arrayList1是否包含11:" + arrayList1.contains(11));//indexOf方法,擷取某個元素在集合中左邊開始第一次出現時的下標//輸出結果:集合arrayList1中第一次出現2的下標為:2System.out.println("集合arrayList1中第一次出現2的下標為:" + arrayList1.indexOf(2));//lastIndexOf方法,擷取某個元素在集合中最後一次(右邊第一次)出現時的下標//輸出結果:集合arrayList1中最後一次出現2的下標為:5System.out.println("集合arrayList1中最後一次出現2的下標為:" + arrayList1.lastIndexOf(2));//remove方法,刪除對應下標的元素//如果傳入的實參類型是byte、short、int和char類型時,根據下標移除arrayList1.remove(0);//運行結果:10 2 3 1 2 3 ergodicArrayList(arrayList1);//移除arrayList1集合中的元素3,只會移除左邊第一個匹配上的資料arrayList1.remove((Integer)3);//運行結果:10 2 1 2 3 ergodicArrayList(arrayList1);//set方法,更新對應下標的元素arrayList1.set(3,1000);//運行結果:10 2 1 1000 3 ergodicArrayList(arrayList1);//toArray方法,將集合轉換成Object類型的數組Object[] array = arrayList1.toArray();//將數群組轉換成字串形式String str = Arrays.toString(array);//運行結果:[10, 2, 1, 1000, 3]System.out.println(str);//清空集合中的所有元素arrayList1.clear();//isEmpty方法,判斷集合是否為空白,若且唯若size方法獲得結果為0時,返回true//運行結果:集合arrayList1是否為空白:trueSystem.out.println("集合arrayList1是否為空白:" + arrayList1.isEmpty());}/** * 遍曆集合 */private static void ergodicArrayList(ArrayList arrayList){//迴圈取出元素for (int index = 0; index < arrayList.size(); index++) {// 使用get方法擷取集合中的資料,擷取出來的資料類型為ObjectObject element = arrayList.get(index);/* * 當使用System.out.println()方法直接輸出參考型別的對象時 * 輸出的是對象.toString()方法的傳回值 * 例如: * System.out.println(element);和 * System.out.println(element.toString());是一樣的 */System.out.print(element);//輸出兩個空格System.out.print(" ");}//換行System.out.print("\n");}}運行結果:1 2 3 1 10 2 3 1 10 2 3 1 2 3 集合arrayList1是否包含10:true集合arrayList1是否包含11:false集合arrayList1中第一次出現2的下標為:2集合arrayList1中最後一次出現2的下標為:510 2 3 1 2 3 10 2 1 2 3 10 2 1 1000 3 [10, 2, 1, 1000, 3]集合arrayList1是否為空白:true
另有Vector集合類,和ArrayList的區別:ArrayList是線程非同步(線程不安全的),Vector是線程同步的(安全執行緒的),因此導致Vector集合的效能非常低下,已基本不用,有興趣的同學可以瞭解即可
既然ArrayList集合插入和刪除效率較低,那麼有沒有比它更快的呢?
接下來看LinkedList集合類
LinkedList類
和ArrayList類基本相同,ArrayList有的方法LinkedList都有;但他們的實現方式不同,LinkedList採用雙向鏈表的資料結構實現,當向集合中添加元素時,集合會建立一個節點Node,這個節點中會儲存當前添加的元素,還會儲存上一個節點和下一個節點,這樣就形成了雙向鏈表這一資料結構。
而這樣的結構修改和刪除效率非常高效,但這個結構中節點與節點之間,在記憶體空間上是不連續的;所以查詢效率要比ArrayList集合的查詢效率低
執行個體:示範LinkedList部分特有方法package collection.list.linkedList;import java.util.LinkedList;/** * LinkedListDemo類 * 示範LinkedListDemo類中常用方法的使用 * @author 學霸聯盟 - 趙燦 */public class LinkedListDemo {public static void main(String[] args) {//建立LinkedList對象LinkedList linkedList = new LinkedList();for (int i = 0; i < 4; i++) {//迴圈向集合中添加資料linkedList.add(i+1);}//運行結果:1 2 3 4 ergodicLinkedList(linkedList);//擷取集合中第一個位置的元素Object first = linkedList.getFirst();//運行結果:集合中第一個元素為:1System.out.println("集合中第一個元素為:" + first);//擷取集合中最後一個位置的元素Object last = linkedList.getLast();//運行結果:集合中最後一個元素為:4System.out.println("集合中最後一個元素為:" + last);//在集合的第一個位置插入元素linkedList.addFirst(0);//在集合的最後一個位置插入元素linkedList.addLast(6);//運行結果:0 1 2 3 4 6 ergodicLinkedList(linkedList);//移除集合中第一個位置的元素linkedList.removeFirst();//移除集合中最後一個位置的元素linkedList.removeLast();//運行結果:1 2 3 4 ergodicLinkedList(linkedList);}/** * 遍曆集合 */private static void ergodicLinkedList(LinkedList linkedList){//迴圈取出元素for (int index = 0; index < linkedList.size(); index++) {// 使用get方法擷取集合中的資料,擷取出來的資料類型為ObjectObject element = linkedList.get(index);/* * 當使用System.out.println()方法直接輸出參考型別的對象時 * 輸出的是對象.toString()方法的傳回值 * 例如: * System.out.println(element);和 * System.out.println(element.toString());是一樣的 */System.out.print(element);//輸出兩個空格System.out.print(" ");}//換行System.out.print("\n");}}運行結果:1 2 3 4 集合中第一個元素為:1集合中最後一個元素為:40 1 2 3 4 6 1 2 3 4
拓展閱讀:《I學霸官方免費教程三十六:Java資料結構之雙向鏈表結構》
總結:
以上我們提到的兩種集合都是繼承自List介面的,他們具有共同的特性,存入的值都是有順序的,可以存入重複的值,可以使用下標訪問元素
不同點
ArrayList:底層由數組實現,初始長度為10,增長因子1.5
缺點:插入和刪除效率較低
優點:修改和查詢效率較高
LinkedList:底層由雙向鏈表實現,沒有初始長度和增長因子
優點:插入和刪除效率較高
缺點:查詢和修改效率較低
本文出自 “學霸聯盟教育官方部落格” 部落格,轉載請與作者聯絡!
I學霸官方免費教程三十一:Java集合架構之List集合