1. 程式人生 > >Java:集合,Collection介面框架圖

Java:集合,Collection介面框架圖

Java集合大致可分為Set、List和Map三種體系,其中Set代表無序、不可重複的集合;List代表有序、重複的集合;而Map則代表具有對映關係的集合。Java 5之後,增加了Queue體系集合,代表一種佇列集合實現。

Java集合框架主要由Collection和Map兩個根介面及其子介面、實現類組成。本文僅探討Collection介面及其子介面、實現類。

目錄

1. Collection介面繼承樹

2. Collection介面是Set、List和Queue介面的父介面,基本操作包括:

  • add(Object o):增加元素
  • addAll(Collection c):...
  • clear():...
  • contains(Object o):是否包含指定元素
  • containsAll(Collection c):是否包含集合c中的所有元素
  • iterator():返回Iterator物件,用於遍歷集合中的元素
  • remove(Object o):移除元素
  • removeAll(Collection c):相當於減集合c
  • retainAll(Collection c):相當於求與c的交集
  • size():返回元素個數
  • toArray():把集合轉換為一個數組

3. Collection的遍歷可以使用Iterator介面或者是foreach迴圈來實現

4. Set子介面

Set集合不允許包含相同的元素,而判斷兩個物件是否相同則是根據equals方法。

4.1 HashSet類

HashSet類是Set介面的典型實現類。特點:

  1. 不能保證元素的排列順序,加入的元素要特別注意hashCode()方法的實現。
  2. HashSet不是同步的,多執行緒訪問同一步HashSet物件時,需要手工同步。
  3. 集合元素值可以是null。

4.2 LinkedHashSet類

LinkedHashSet類也是根據元素的hashCode值來決定元素的儲存位置,但它同時使用連結串列維護元素的次序。與HashSet相比,特點:

  1. 對集合迭代時,按增加順序返回元素。
  2. 效能略低於HashSet,因為需要維護元素的插入順序。但迭代訪問元素時會有好效能,因為它採用連結串列維護內部順序。

4.3 SortedSet介面及TreeSet實現類

TreeSet類是SortedSet介面的實現類。因為需要排序,所以效能肯定差於HashSet。與HashSet相比,額外增加的方法有:

  1. first():返回第一個元素
  2. last():返回最後一個元素
  3. lower(Object o):返回指定元素之前的元素
  4. higher(Obect o):返回指定元素之後的元素
  5. subSet(fromElement, toElement):返回子集合

可以定義比較器(Comparator)來實現自定義的排序。預設自然升序排序。

4.4 EnumSet類

EnumSet類是專為列舉類設計的集合類,EnumSet中的所有元素都必須是指定列舉型別的列舉值。《Effective Java》第32條,用EnumSet代替位域,示範:

// EnumSet - a modern replacement for bit fields - Page 160
import java.util.*;

public class Text {
    public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH }

    // Any Set could be passed in, but EnumSet is clearly best
    public void applyStyles(Set<Style> styles) {
        // Body goes here
    }

    // Sample use
    public static void main(String[] args) {
        Text text = new Text();
        text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC));
    }
}

5. List子介面

List子介面是有序集合,所以與Set相比,增加了與索引位置相關的操作:

  • add(int index, Object o):在指定位置插入元素
  • addAll(int index, Collection c):...
  • get(int index):取得指定位置元素
  • indexOf(Obejct o):返回物件o在集合中第一次出現的位置
  • lastIndexOf(Object o):...
  • remove(int index):刪除並返回指定位置的元素
  • set(int index, Object o):替換指定位置元素
  • subList(int fromIndex, int endIndex):返回子集合

5.1 ArrayList和Vector實現類

  1. 這兩個類都是基於陣列實現的List類。
  2. ArrayList是執行緒不安全的,而Vector是執行緒安全的。但Vector的效能會比ArrayList低,且考慮到相容性的原因,有很多重複方法。
  3. Vector提供一個子類Stack,可以挺方便的模擬“棧”這種資料結構(LIFO,後進先出)。

結論:不推薦使用Vector類,即使需要考慮同步,即也可以通過其它方法實現。同樣我們也可以通過ArrayDeque類或LinkedList類實現“棧”的相關功能。所以Vector與子類Stack,建議放進歷史吧。

5.2 LinkedList類

不像ArrayList是基於陣列實現的線性表,LinkedList類是基於連結串列實現的。

另外還有固定長度的List:Arrays工具類的方法asList(Object... a)可以將陣列轉換為List集合,它是Arrays內部類ArrayList的例項,特點是不可以增加元素,也不可以刪除元素。

6. Queue子介面

Queue用於模擬佇列這種資料結構,實現“FIFO”等資料結構。通常,佇列不允許隨機訪問佇列中的元素。

Queue 介面並未定義阻塞佇列的方法,而這在併發程式設計中是很常見的。BlockingQueue 介面定義了那些等待元素出現或等待佇列中有可用空間的方法,這些方法擴充套件了此介面。

Queue 實現通常不允許插入 null 元素,儘管某些實現(如 LinkedList)並不禁止插入 null。即使在允許 null 的實現中,也不應該將 null 插入到 Queue 中,因為 null 也用作 poll 方法的一個特殊返回值,表明佇列不包含元素。

基本操作:

  • boolean add(E e) : 將元素加入到隊尾,不建議使用
  • boolean offer(E e): 將指定的元素插入此佇列(如果立即可行且不會違反容量限制),當使用有容量限制的佇列時,此方法通常要優於 add(E),後者可能無法插入元素,而只是丟擲一個異常。推薦使用此方法取代add
  • E remove(): 獲取頭部元素並且刪除元素,不建議使用
  • E poll(): 獲取頭部元素並且刪除元素,佇列為空返回null;推薦使用此方法取代remove
  • E element(): 獲取但是不移除此佇列的頭
  • E peek(): 獲取佇列頭部元素卻不刪除元素,佇列為空返回null
    @Test
        public void testQueue() {
            Queue<String> queue = new LinkedList<String>();
            queue.offer("1.你在哪兒?");
            queue.offer("2.我在這裡。");
            queue.offer("3.那你又在哪兒呢?");
            String str = null;
            while ((str = queue.poll()) != null) {
                System.out.println(str);
            }
        }

    6.1 PriorityQueue類

PriorityQueue儲存佇列元素的順序並不是按照加入佇列的順序,而是按佇列元素的大小重新排序當呼叫peek()或者是poll()方法時,返回的是佇列中最小的元素。當然你可以與TreeSet一樣,可以自定義排序。自定義排序的一個示範:

@Test
    public void testPriorityQueue() {
        PriorityQueue<Integer> pq = new PriorityQueue<Integer>(20, new Comparator<Integer>() {
            public int compare(Integer i, Integer j) {
                // 對數字進行奇偶分類,然後比較返回;偶數有較低的返回值(對2取餘數然後相減),奇數直接相減。
                int result = i % 2 - j % 2;
                if (result == 0)
                    result = i - j;
                return result;
            }
        });

        // 倒序插入測試資料
        for (int i = 0; i < 20; i++) {
            pq.offer(20 - i);
        }

        // 列印結果,偶數因為有較低的值,所以排在前面
        for (int i = 0; i < 20; i++) {
            System.out.println(pq.poll());
        }
    }

輸出:

2,4,6,8,10,12,14,16,18,20,1,3,5,7,9,11,13,15,17,19,

6.2 Deque子介面與ArrayDeque類

Deque代表一個雙端佇列,可以當作一個雙端佇列使用,也可以當作“棧”來使用,因為它包含出棧pop()與入棧push()方法。

ArrayDeque類為Deque的實現類,陣列方式實現。方法有:

  • addFirst(Object o):元素增加至佇列開頭
  • addLast(Object o):元素增加至佇列末尾
  • poolFirst():獲取並刪除佇列第一個元素,佇列為空返回null
  • poolLast():獲取並刪除佇列最後一個元素,佇列為空返回null
  • pop():“棧”方法,出棧,相當於removeFirst()
  • push(Object o):“棧”方法,入棧,相當於addFirst()
  • removeFirst():獲取並刪除佇列第一個元素
  • removeLast():獲取並刪除佇列最後一個元素

6.3 實現List介面與Deque介面的LinkedList類

LinkedList類是List介面的實現類,同時它也實現了Deque介面。因此它也可以當做一個雙端佇列來用,也可以當作“棧”來使用。並且,它是以連結串列的形式來實現的,這樣的結果是它的隨機訪問集合中的元素時效能較差,但插入與刪除操作效能非常出色。

7. 各種線性表選擇策略

  1. 陣列:是以一段連續記憶體儲存資料的;隨機訪問是最快的,但不支援插入、刪除、迭代等操作。
  2. ArrayList與ArrayDeque:以陣列實現;隨機訪問速度還行,插入、刪除、迭代操作速度一般;執行緒不安全。
  3. Vector:以陣列實現;隨機訪問速度一般,插入、刪除、迭代速度不太好;執行緒安全的。
  4. LinkedList:以連結串列實現;隨機訪問速度不太好,插入、刪除、迭代速度非常快。