Java集合框架總結(4)——List接口的使用

List集合表明一個有序集合,集合中每一個元素都有其對應的順序索引。List集合容許使用重複元素,能夠經過索引來訪問指定位置的集合元素。java

一、List接口和ListIterator接口

    List做爲Collection接口的子接口,可使用Collection接口裏的所有方法。List是有序集合,因此List集合裏增長了一些根據索引來操做集合元素的方法:數組

  • void add(int index, Object element):將元素element插入在List集合的index處。
  • boolean addAll(int index, Collection c):將集合c所包含的全部元素都插入在List集合的index處。
  • Object get(int index):返回集合index索引處的元素。
  • int lastIndexOf(Object o):返回對象o在List集合中最後一次出現的位置索引。
  • Object remove(int index):刪除並返回index索引處的元素。
  • Object set(int index, Object element):將index索引處的元素替換成element對象,返回新元素。
  • List subList(int fromIndex, int toIndex):返回從索引fromIndex(包含)到索引toIndex(不包含)處全部集合元素組成的子集合。

    List集合能夠根據索引來插入、替換和刪除集合元素。安全

示例程序:數據結構

public class TestList
{
    public static void main(String[] args)
    {
        List books = new ArrayList();
        //向books集合中添加三個元素
        books.add(new String("輕量級J2EE企業應用實戰"));
        books.add(new String("Struts2權威指南"));
        books.add(new String("基於J2EE的Ajax寶典"));
        System.out.println(books);
        //將新字符串對象插入在第二個位置
        books.add(1 , new String("ROR敏捷開發最佳實踐")); //已添加的對象,和下面語句作對比
        for (int i = 0 ; i < books.size() ; i++ )
        {
            System.out.println(books.get(i));
        }
        //刪除第三個元素
        books.remove(2);
        System.out.println(books);
        //判斷指定元素在List集合中位置:輸出1,代表位於第二位
        System.out.println(books.indexOf(new String("ROR敏捷開發最佳實踐"))); //新建立的對象
        //將第二個元素替換成新的字符串對象
        books.set(1, new String("Struts2權威指南"));
        System.out.println(books);
        //將books集合的第二個元素(包括)到第三個元素(不包括)截取稱子集合
        System.out.println(books.subList(1 , 2));

    }
}

程序運行結果:框架

[輕量級J2EE企業應用實戰, Struts2權威指南, 基於J2EE的Ajax寶典] 
輕量級J2EE企業應用實戰 
ROR敏捷開發最佳實踐 
Struts2權威指南 
基於J2EE的Ajax寶典 
[輕量級J2EE企業應用實戰, ROR敏捷開發最佳實踐, 基於J2EE的Ajax寶典] 

[輕量級J2EE企業應用實戰, Struts2權威指南, 基於J2EE的Ajax寶典] 
[Struts2權威指南]工具

程序說明:List集合可使用普通for循環來遍歷集合元素。List判斷兩個對象相等只要經過equals方法比較返回true便可。如在判斷「ROR敏捷開發最佳實踐」字符串的位置是,新建立了一個新字符串對象,可是程序仍返回第一次建立字符串對象的位置。當調用List的set(int index, Object element)方法來改變List集合指定索引處元素時,指定的索引必須是List集合的有效索引。性能

     與set只提供了一個iterator()方法不一樣,List還額外提供了一個listIteratro()方法,該方法返回一個ListIterator對象,ListIterator接口繼承了Iterator接口,提供了專門操做List的方法。優化

ListIterator接口在Iterator接口基礎上增長了以下方法:spa

  • boolean hasPrevious():返回該迭代器關聯集合是否還有上一個元素。
  • Object previous():返回該迭代器上一個元素。
  • void add():在指定位置插入一個元素。

程序示例:線程

public static void main(String[] args)
    {
        String[] books = {
            "Struts2權威指南",
            "輕量級J2EE企業應用實戰"
        };
        List bookList = new ArrayList();
        for (int i = 0; i < books.length ; i++ )
        {
            bookList.add(books[i]);
        }
        ListIterator lit = bookList.listIterator();
        while (lit.hasNext())
        {
            System.out.println(lit.next());
            lit.add("-------分隔符-------");
        }
        System.out.println("==========下面開始反向迭代===========");
        while(lit.hasPrevious())
        {
            System.out.println(lit.previous());
        }
    }
}

程序運行結果:

Struts2權威指南 
輕量級J2EE企業應用實戰 
==========下面開始反向迭代=========== 
-------分隔符------- 
輕量級J2EE企業應用實戰 
-------分隔符------- 
Struts2權威指南

程序說明:List經過ListTterator迭代集合時,便可採用next()方法進行正向迭代,迭代過程當中可使用add()方法向上一次迭代元素的後面添加一個新元素。同時程序演示了向前迭代。

 二、ArrayList和Vector實現類

    ArrayList和Vector做爲List類的兩個典型實現,徹底支持前面介紹的List接口所有功能。

    ArrayList和Vector類都是基於數組實現的List類,他們封裝了一個動態再分配的Object[]數組。每一個ArrayList或Vector對象有一個capacity屬性,表示它們所封裝的Object[]數組的長度。capacity會添加元素的個數而自動增長。當向集合中添加大量元素時,可使用ensureCapacity方法一次性地增長capacity。這能夠減小增長重分配次數,從而提供性能。capacity大小也能夠在建立時就指定,該屬性默認爲10.

ArrayList和Vector提供以下兩個方法來操做capacity屬性:

  • void ensureCapacity(int minCapacity):將ArrayList或Vector集合的capacity增長minCapacity。
  • void trimToSize():調整ArrayList或Vector集合的capacity爲列表當前大小。程序可調用該方法來減小ArrayList或Vector集合對象存儲空間。

    ArrayList和Vector用法幾乎相同,Vector是一個古老的集合(從JDK1.0),起初Java尚未提供系統的集合框架,因此Vector裏提供了一些方法名很長的方法:例如addElement(Object obj), 等同於add()方法。從JDK1.2之後,Java提供了系統的集合框架,就將Vector改成實習List接口,做爲List的實習之一,從而致使Vector裏有一些功能重複的方法。Vector具備不少缺點,一般儘可能少用Vector實現類。

 

   ArrayList和Vector的區別:ArrayList是線程不安全的,多個線程訪問同一個ArrayList集合時,若是有超過一條線程修改了ArrayList集合,則程序必須手動保證該集合的同步性。Vector集合則是線程安全的,無線程序保證該集合的同步性。由於Vector是線程安全的,因此Vector的性能比ArrayList的性能要低。實際上,即便保證List集合線程安全,一樣不推薦使用Vector實現類。Collections工具類,能夠將一個ArrayList變成線程安全的

 

   Vector還提供了一個Stack子類,它用於模擬了」棧「這種數據結構,」棧「一般是指」後進先出「(LIFO)的容器。最後」push「進棧的元素,將最早被」pop「出棧。與Java中其餘集合同樣,進棧出棧的都是Object,所以從棧中取出元素後必須作類型轉換,除非你只是使用Object具備的操做。因此stack類提供了以下幾個方法:

  • Object peek():返回」棧「的第一個元素,但並不將該元素」pop「出棧。
  • Object pop():返回」棧「的第一個元素,並將該元素」pop「出棧。
  • void push(Object item):將一個元素」push「進棧,最後一個進」棧「的元素老是位於」棧「頂。

程序示例:

public class TestVector
{
    public static void main(String[] args)
    {
        Stack v = new Stack();
        //依次將三個元素push入"棧"
        v.push("Struts2權威指南");
        v.push("輕量級J2EE企業應用實戰");
        v.push("ROR敏捷開發最佳實踐");
        //輸出:[Struts2權威指南, 輕量級J2EE企業應用實戰, ROR敏捷開發最佳實踐]
        System.out.println(v);
        //訪問第一個元素,但並不將其pop出"棧",輸出:ROR敏捷開發最佳實踐
        System.out.println(v.peek());
        //依然輸出:[Struts2權威指南, 輕量級J2EE企業應用實戰, ROR敏捷開發最佳實踐]
        System.out.println(v);
        //pop出第一個元素,輸出:ROR敏捷開發最佳實踐
        System.out.println(v.pop());
        //依然輸出:[Struts2權威指南, 輕量級J2EE企業應用實戰]
        System.out.println(v);
    }
}

程序運行結果:

[Struts2權威指南, 輕量級J2EE企業應用實戰, ROR敏捷開發最佳實踐] 
ROR敏捷開發最佳實踐 
[Struts2權威指南, 輕量級J2EE企業應用實戰, ROR敏捷開發最佳實踐] 
ROR敏捷開發最佳實踐 
[Struts2權威指南, 輕量級J2EE企業應用實戰]

   三、LinkedList實現類

    List還有一個LinkedList的實現,它是一個基於鏈表實現的List類,對於順序訪問集合中的元素進行了優化,特別是當插入、刪除元素時速度很是快。由於LinkedList即實現了List接口,也實現了Deque接口(雙向隊列),Deque接口是Queue接口的子接口,它表明一個雙向列表,Deque接口裏定義了一些能夠雙向操做隊列的方法

  • void addFirst(Object e):將制定元素插入該雙向隊列的開頭。
  • void addLast(Object e):將制定元素插入該雙向隊列的末尾。
  • Iterator descendingIterator():返回以該雙向隊列對應的迭代器,該迭代器將以逆向順序來迭代隊列中的元素。
  • Object getFirst():獲取、但不刪除雙向隊列的第一個元素。
  • Object getLast(): 獲取、但不刪除雙向隊列的最後一個元素。
  • boolean offerFirst(Object e): 將指定的元素插入該雙向隊列的開頭。
  • boolean offerLast(Object e): 將指定的元素插入該雙向隊列的末尾。
  • Object peekFirst(): 獲取、但不刪除該雙向隊列的第一個元素:若是此雙端隊列爲空,則返回null。
  • Object peekLast():獲取、但不刪除該雙向隊列的最後一個元素:若是此雙端隊列爲空,則返回null。
  • Object pollFirst():獲取、並刪除該雙向隊列的第一個元素:若是此雙端隊列爲空,則返回null。
  • Object pollLast():獲取、並刪除該雙向隊列的最後一個元素:若是此雙端隊列爲空,則返回null。
  • Object pop():pop出該雙向隊列所表示的棧中第一個元素。
  • void push(Object e):將一個元素push進該雙向隊列所表示的棧中(即該雙向隊列的頭部)。
  • Object removerFirst():獲取、並刪除該雙向隊列的最後一個元素。
  • Object removeFirstOccurrence(Object o):刪除該雙向隊列的第一次的出現元素o。
  • Object removeLast():獲取、並刪除該雙向隊列的最後一個元素。
  • Object removeLastOccurrence(Object o):刪除該雙向隊列的最後一次出現的元素o。

從上面方法中能夠看出,LinkedList不只能夠當成雙向隊列使用,也能夠當成「棧」使用。同時,LinkedList實現了List接口,因此還被當成List使用。

程序示例:

public class TestLinkedList
{
    public static void main(String[] args)
    {
        LinkedList books = new LinkedList();
        //將字符串元素加入隊列的尾部
        books.offer("Struts2權威指南");
        //將一個字符串元素入棧
        books.push("輕量級J2EE企業應用實戰");
        //將字符串元素添加到隊列的頭部
        books.offerFirst("ROR敏捷開發最佳實踐");
        for (int i = 0; i < books.size() ; i++ )
        {
            System.out.println(books.get(i));
        }
        //訪問、並不刪除隊列的第一個元素
        System.out.println(books.peekFirst());
        //訪問、並不刪除隊列的最後一個元素
        System.out.println(books.peekLast());
        //採用出棧的方式將第一個元素pop出隊列
        System.out.println(books.pop());
        //下面輸出將看到隊列中第一個元素被刪除
        System.out.println(books);
        //訪問、並刪除隊列的最後一個元素
        System.out.println(books.pollLast());
        //下面輸出將看到隊列中只剩下中間一個元素:輕量級J2EE企業應用實戰
        System.out.println(books);

    }
}

程序運行結果:

ROR敏捷開發最佳實踐 
輕量級J2EE企業應用實戰 
Struts2權威指南 
ROR敏捷開發最佳實踐 
Struts2權威指南 
ROR敏捷開發最佳實踐 
[輕量級J2EE企業應用實戰, Struts2權威指南] 
Struts2權威指南 
[輕量級J2EE企業應用實戰]

說明:程序中示範了LinkedList做爲雙向隊列、棧和List集合的用法。LinkedList與ArrayList、Vector的實現機制徹底不一樣,ArrayList、Vector內部以數組的形式來保存集合中的元素,所以隨機訪問集合元素上有較好的性能;而LinkedList內部以鏈表的形式來保存集合中的元素,所以隨機訪問集合時性能較差,但在插入、刪除元素時性能很是出色(只需改變指針所指的地址便可)。Vector因實現了線程同步功能,因此各方面性能有所降低。

 

關於使用List集合的幾點建議:

  • 若是須要遍歷List集合元素,對應ArrayList、Vector集合,則應該使用隨機訪問方法(get)來遍歷集合元素,這樣性能更好。對應LinkedList集合,則應採用迭代器(Iterator)來遍歷集合元素。
  • 若是須要常常執行插入、刪除操做來改變Lst集合大小,則應該使用LinkedList集合,而不是ArrayList。
  • 若是多條線程須要同時訪問List集合中的元素,能夠考慮使用Vector這個同步實現。
相關文章
相關標籤/搜索