Java:集合,Collection接口框架圖


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

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

目錄

1. Collection接口繼承樹
2. Collection接口基本操作
3. Collection的遍歷
4. Set子接口
  4.1 HashSet類
  4.2 LinkedHashSet類
  4.3 SortedSet接口及TreeSet實現類
  4.4 EnumSet類
5. List子接口
  5.1 ArrayList和Vector實現類
  5.2 LinkedList類
6. Queue子接口
  6.1 PriorityQueue類
  6.2 Deque子接口與ArrayDeque類
  6.3 實現List接口與Deque接口的LinkedList類
7. 各種線性表選擇策略

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循環來實現

 參考:Java:集合,數組(Array)、集合(List/Set/Queue)、映射(Map)等的迭代遍歷,比如:ArrayList,LinkedList,HashSet,HashMap

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:以鏈表實現;隨機訪問速度不太好,插入、刪除、迭代速度非常快。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM