1. 程式人生 > 實用技巧 >Java 集合 -- List

Java 集合 -- List

Java Collection 簡介

Java標準庫自帶的java.util包提供了集合類:Collection,它是除Map外所有其他集合類的根介面。

Java的java.util包主要提供了以下三種類型的集合:

  • List:一種有序列表的集合,例如,按索引排列的Student的List;

  • Set:一種保證沒有重複元素的集合,例如,所有無重複名稱的Student的Set;

  • Map:一種通過鍵值(key-value)查詢的對映表集合,例如,根據Student的name查詢對應Student的Map。

Java Collection 介面的繼承關係如下圖:

Java集合的設計有幾個特點:

  • 一是實現了介面和實現類相分離,例如,有序表的介面是List,具體的實現類有ArrayList,LinkedList等,

  • 二是支援泛型,我們可以限制在一個集合中只能放入同一種資料型別的元素,例如:

List<String> list = new ArrayList<>(); // 只能放入String型別

最後,Java訪問集合總是通過統一的方式——迭代器(Iterator)來實現,它最明顯的好處在於無需知道集合內部元素是按什麼方式儲存的。

部分遺留的集合類(不建議使用):

  • Hashtable:一種執行緒安全的Map實現;

  • Vector:一種執行緒安全的List實現;

  • Stack:基於Vector實現的LIFO的棧。

還有一小部分介面是遺留介面,也不應該繼續使用

  • Enumeration:已被Iterator取代。

使用 List

在集合類中,List是最基礎的一種集合:它是一種有序列表。List的索引和陣列一樣,從0開始。

List 的實現類 ArrayList

在實際應用中,需要增刪元素的有序列表,我們使用最多的是ArrayList。實際上,ArrayList在內部使用了陣列來儲存所有元素。

ArrayList把新增和刪除的操作封裝起來,讓我們操作List類似於運算元組,卻不用關心內部元素如何移動。

List 的實現類 LinkedLsit

LinkedList通過“連結串列”也實現了List介面。在LinkedList中,它的內部每個元素都指向下一個元素.

比較一下ArrayList和LinkedList:

通常情況下,我們總是優先使用ArrayList。

List 的特點

List介面允許我們新增重複的元素,即List內部的元素可以重複:

public class ListMain {
    public static void main(String[] args){
        // 例項化一個 ArrayList 列表,命名為 list
        // 其中只能存放String 型別元素
        List<String> list = new ArrayList<>();
        list.add("apple"); // 使用 add()方法新增元素
        list.add("pear");
        list.add("apple");// 允許重複新增元素
        System.out.println(list.size()); // 使用size()方法獲取列表長度
        System.out.println(list);
    }
}

List 允許新增 null

public class ListMain {
    public static void main(String[] args){
        // 例項化一個 ArrayList 列表,命名為 list
        // 其中只能存放String 型別元素
        List<String> list = new ArrayList<>();
        list.add("apple"); // 使用 add()方法新增元素
        list.add(null);
        list.add("apple");// 允許重複新增元素
        String second = list.get(1); // 獲取列表元素,下標從0開始
        System.out.println(second);
        System.out.println(list);
    }
}

建立 List

除了使用ArrayList和LinkedList,我們還可以通過List介面提供的of()方法,根據給定元素快速建立List

List<Integer> list = List.of(1, 2, 5);

但是List.of()方法不接受null值,如果傳入null,會丟擲NullPointerException異常。

注意:只有JDK9及以上,才支援 of()方法快速建立List,JDK8不支援。

遍歷 List

可以用for迴圈根據索引配合get()方法遍歷:

public class ListMain {
    public static void main(String[] args){
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("null");
        list.add("apple");
        for (int i=0; i<list.size(); i++){
            String s = list.get(i);
            System.out.println(s);
        }
    }
}

因為get(int)方法只有ArrayList的實現是高效的,換成LinkedList後,索引越大,訪問速度越慢。

所以要始終堅持使用迭代器Iterator來訪問List

Iterator本身也是一個物件,但它是由List的例項呼叫iterator()方法的時候建立的。

Iterator<String> it = list.iterator()

Iterator物件知道如何遍歷一個List,並且不同的List型別,返回的Iterator物件實現也是不同的,但總是具有最高的訪問效率。

Iterator物件有兩個方法:

  • boolean hasNext()判斷是否有下一個元素,

  • next()返回下一個元素。

因此,使用Iterator遍歷List程式碼如下:

public class ListMain {
 public static void main(String[] args){
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("null");
        list.add("apple");
        Iterator<String> iterator = list.iterator();
        for (;iterator.hasNext();){
            String s = iterator.next();
            System.out.println(s);
        }
    }
}

記住,通過Iterator遍歷List永遠是最高效的方式。

並且,由於Iterator遍歷是如此常用,所以,Java的增強for迴圈本身就可以幫我們使用Iterator遍歷。

把上面的程式碼再改寫如下:

public class ListMain {
 public static void main(String[] args){
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("null");
        list.add("apple");
        // Iterator<String> iterator = list.iterator();
        for (String s:list){ // 增強for迴圈
            // String s = iterator.next();
            System.out.println(s);
        }
    }
}

上述程式碼就是我們編寫遍歷List的常見程式碼。

實際上,只要實現了Iterable介面的集合類都可以直接用增強for迴圈來遍歷.

Java編譯器本身並不知道如何遍歷集合物件,但它會自動把增強for迴圈變成Iterator的呼叫,原因就在於Iterable介面定義了一個Iterator iterator()方法,強迫集合類必須返回一個Iterator例項。

List 與 Array 的轉換

array 表示陣列。

把List變為Array有三種方法,

  • 第一種是呼叫toArray()方法直接返回一個Object[]陣列

  • 第二種方式是給toArray(T[])傳入一個型別相同的Array,List內部自動把元素複製到傳入的Array中

  • 最後一種更簡潔的寫法是通過List介面定義的T[] toArray(IntFunction<T[]> generator)方法

每天學習一點點,每天進步一點點。