位元詩人 [Java] 程式設計教學:使用 ArrayList 物件

Java陣列
Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

前言

ArrayList 是 Java 串列 (List) 的其中一種實作。ArrayList 內部是動態陣列 (dynamic array)。由於 Java 不支援運算子重載 (operator overloading),ArrayList 無法用 [...] 存取元素。

建立 ArrayList 物件

引入物件庫

在預設情況下,Java 並不會自動引入 ArrayList。若要使用此容器,需先加入以下套件:

import java.util.ArrayList;
import java.util.List;

在部分範例中,也可能看到如下寫法:

import java.util.*

此種寫法會一次引入整個套件,容易造成命名空間汙染,因此通常不建議使用。

建立 ArrayList 物件

可以使用以下敘述來建立 ArrayList 物件:

List<Integer> lst = new ArrayList<Integer>();

建立 ArrayList 的方式是透過 new 關鍵字,這點與建立陣列的概念相似。

此處雖然建立的是 ArrayList 物件,但變數 lst 的型態宣告為 List。這是因為我們通常只需要使用 List 所提供的公開方法(public methods)。未來若需要替換為其他 List 的實作,只需修改建立物件的部分,其餘程式碼可保持不變,有助於提升程式的彈性與可維護性。

<...> 為泛型程式設計(generic programming)的語法,用於將資料型態參數化。不過,Java 的泛型不支援基礎型態(primitive types),因此此處需使用 Integer 類別。

若需要使用 ArrayList 特有的方法,則可以改用以下宣告方式:

ArrayList<Integer> lst = new ArrayList<Integer>();

由於 Java 泛型不支援基礎型態,以下寫法是錯誤的:

/* WRONG CODE. */
List<int> lst = new ArrayList<int>();

存取 ArrayList 物件的元素

中由於 Java 不支援運算子重載,無法使用 [...] 存取元素。替代的方式是用 get() 函式取得元素,使用 add(E) 函式從尾端新增元素。參考以下範例:

import java.util.ArrayList;
import java.util.List;

public class MainProgram
{
    public static void main (String[] args)
    {
        /* Create a ArrayList object. */
        List<Integer> lst = new ArrayList<Integer>();

        /* Some integer data. */
        int data[] = {1, 2, 3, 4, 5};

        for (int n : data) {
            /* Append an element to
                the rear of the list. */
            lst.add(n);
        }

        /* Retrieve an element from the list. */
        assertCond(5 == lst.get(4));
    }

    /* Home-made assert. */
    public static void assertCond (boolean cond)
    {
        if (!cond)
            throw new IllegalArgumentException("Wrong condition");
    }
}

女如果要在指定位置新增元素,則改用 add(i, E) 函式。這兩個函式是同名的,這項特性稱為函式重載 (function overloading):

for (int i = 0; i < data.length; ++i) {
    /* Add an element to a specific location
        of the list. */
    lst.add(i, data[i]);
}

add(i, E) 函式的 i 必需要介於 0 和容器寬度 (不包含) 之間,否則會拋出 IndexOutOfBoundsException 例外。

注意 set(i, E) 函式無法增長 ArrayList 寬度。故以下程式碼會引發錯誤:

for (int i = 0; i < data.length; ++i) {
    /* WRONG CODE. */
    lst.set(i, data[i]);
}

檢查特定元素是否存在

使用 contains() 函式來檢查特定元素是否存在。參考以下範例:

import java.util.ArrayList;
import java.util.List;

public class MainProgram
{
    public static void main (String[] args)
    {
        List<Integer> lst = new ArrayList<Integer>();

        int data[] = {1, 2, 3, 4, 5};

        for (int n : data)
            lst.add(n);

        /* Check whether an element exists. */
        assertCond(lst.contains(5));
    }

    /* Home-made assert. */
    public static void assertCond (boolean cond)
    {
        if (!cond)
            throw new IllegalArgumentException("Wrong condition");
    }
}

走訪 ArrayList 物件

使用計數器 (Counter)

ArrayList 在本質上是陣列,當然可以用計數器來走訪:

for (int i = 0; i < lst.size(); ++i)
    System.out.println(lst.get(i));

可以使用計數器的前提是程式設計者知道 ArrayList 以非負整數為索引,每次遞增 1。不一定每種容器都能使用計數器。

使用隱式迭代器 (Implicit Iterator)

ArrayList 內部隱藏迭代器,故以下程式碼是合理的:

for (int n : lst)
    System.out.println(n);

另外可以注意到此處變數 n 的資料型態是 int 而非 Integer,這裡用到了 Java 的自動型態轉換。手動在基礎型態和其相關類別間轉換的程式碼太繁瑣了,所以 Java 自動完成這些細部過程。

使用顯式迭代器 (Explicit Iterator)

既然有隱式迭代器可用,也可以直接提出顯式迭代器來用。參考以下範例:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class MainProgram
{
    public static void main (String[] args)
    {
        List<Integer> lst = new ArrayList<Integer>();

        int data[] = {1, 2, 3, 4, 5};

        for (int n : data)
            lst.add(n);

        Iterator<Integer> it = lst.iterator();
        while (it.hasNext()) {
            int n = it.next();
            System.out.println(n);
        }
    }
}

此處的程式碼和前一小節的 for 迴圈是等效的,但寫起來比較長。所以這樣的模式是不必要的,本小節範例僅供參考。

關於作者

位元詩人 (ByteBard) 是資訊領域碩士,喜歡用開源技術來解決各式各樣的問題。這類技術跨平台、重用性高、技術生命長。

除了開源技術以外,位元詩人喜歡日本料理和黑咖啡,會一些日文,有時會自助旅行。