首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 基礎:java.util 包下常用資料結構詳解

     編輯:Java 相關知識

線性表、鏈表、哈希表是常用資料結構,進行 Java 開發時,JDK 已提供一系列相應類實現基本資料結構,均位於 java.util 包中。本文嘗試透過簡單描述,闡述各類別的作用與正確使用方式。

Collection
 ├List
 │├LinkedList
 │├ArrayList
 │└Vector
 │ └Stack
 └Set
Map
 ├Hashtable
 ├HashMap
 └WeakHashMap

Collection 介面

Collection 是最基本的集合介面,代表一組 Object(即元素)。部分 Collection 允許重複元素,部分不允許;部分可排序,部分不可。Java SDK 不提供直接繼承自 Collection 的類,提供的類皆繼承自其「子介面」如 List 和 Set。

所有實現 Collection 介面的類必須提供兩個標準構造函數:無參構造函數創建空 Collection;有一個 Collection 參數的構造函數創建新 Collection,新 Collection 與傳入 Collection 擁有相同元素,允許用戶複製 Collection。

如何遍歷 Collection 中的每個元素?無論實際類型,皆支援 iterator() 方法,返回迭代器,可逐一訪問元素。典型用法:

Iterator it = collection.iterator();
while(it.hasNext()) {
    Object obj = it.next();
}

由 Collection 衍生的兩個介面是 List 和 Set。

主要方法

  • boolean add(Object o) 添加物件到集合
  • boolean remove(Object o) 刪除指定物件
  • int size() 返回元素數量
  • boolean contains(Object o) 查找是否有指定物件
  • boolean isEmpty() 判斷是否為空
  • Iterator iterator() 返回迭代器
  • boolean containsAll(Collection c) 查找是否包含集合 c 的元素
  • boolean addAll(Collection c) 將集合 c 所有元素添加給該集合
  • void clear() 刪除所有元素
  • void removeAll(Collection c) 刪除集合 c 中也有的元素
  • void retainAll(Collection c) 刪除集合 c 中不包含的元素

List 介面

List 是有序的 Collection,可精確控制每個元素插入位置。用戶可使用索引(元素在 List 中的位置,類似陣列下標)訪問元素,類似 Java 陣列。與 Set 不同,List 允許重複元素。

除了 iterator(),List 還提供 listIterator() 返回 ListIterator,比標準 Iterator 多出 add() 等方法,允許添加、刪除、設定元素,並能向前或向後遍歷。

實現 List 介面的常用類有 LinkedList、ArrayList、Vector 和 Stack。

主要方法

  • void add(int index, Object element) 在指定位置添加物件
  • boolean addAll(int index, Collection c) 將集合 c 元素添加到指定位置
  • Object get(int index) 返回指定位置元素
  • int indexOf(Object o) 返回第一次出現元素 o 的位置
  • Object remove(int index) 刪除指定位置元素
  • Object set(int index, Object element) 用元素 element 取代位置 index 上的元素,返回被取代元素

LinkedList 類

實現 List 介面,允許 null 元素。額外提供在首部或尾部的 get、remove、insert 方法,可作堆疊、佇列或雙向佇列使用。注意 LinkedList 無同步方法,多線程並發訪問需自行實現同步,可用 Collections.synchronizedList(new LinkedList(...)) 構造同步 List。

ArrayList 類

實現可變大小陣列,允許所有元素包括 null,非同步。size、isEmpty、get、set 運行時間為常數;add 方法攤銷常數時間,添加 n 個元素需 O(n) 時間,其他方法線性時間。每個實例有容量,隨添加元素自動增加,增長演算法未定義。需插入大量元素時,可預先呼叫 ensureCapacity 提高效率。同 LinkedList,非同步。

Vector 類

與 ArrayList 相似,但 Vector 是同步的。由 Vector 創建的 Iterator 雖與 ArrayList 同介面,但因 Vector 同步,若一個 Iterator 被創建並使用時,另一線程改變 Vector 狀態(如增刪元素),調用 Iterator 方法將拋出 ConcurrentModificationException,必須捕獲該異常。

Stack 類

繼承自 Vector,實現後進先出堆疊。提供 5 個額外方法使 Vector 可作堆疊使用:基本 push 和 pop,peek 取得堆疊頂元素,empty 測試是否為空,search 檢測元素在堆疊中的位置。新創建的 Stack 為空堆疊。

Set 介面

Set 是不包含重複元素的 Collection,任意兩元素 e1、e2 滿足 e1.equals(e2)=false,最多一個 null 元素。構造函數有約束:傳入的 Collection 參數不能包含重複元素。須小心操作可變物件:若 Set 中可變元素改變狀態導致 Object.equals(Object)=true 將引發問題。

Map 介面

Map 未繼承 Collection 介面,提供 key 到 value 的映射。一個 Map 不能包含相同 key,每個 key 只映射一個 value。Map 介面提供 3 種集合視圖:key 集合、value 集合、key-value 映射集合。

主要方法

  • boolean equals(Object o) 比較物件
  • boolean remove(Object o) 刪除物件
  • put(Object key, Object value) 添加 key 和 value

Hashtable 類

繼承 Map 介面,實現 key-value 映射哈希表。任何非空物件可作 key 或 value。put(key, value) 添加,get(key) 取出,兩基本操作時間開銷為常數。透過 initial capacity 和 load factor 調整性能,預設 load factor 0.75 較好平衡時間與空間。增大 load factor 可節省空間但查找時間增大,影響 get 和 put。

簡單示例:

Hashtable numbers = new Hashtable();
numbers.put("one", new Integer(1));
numbers.put("two", new Integer(2));
numbers.put("three", new Integer(3));
Integer n = (Integer)numbers.get("two");
System.out.println("two = " + n);

作為 key 的物件將通過計算散列函數確定 value 位置,故任何作 key 的物件必須實現 hashCode 和 equals 方法。若兩物件相同(equals 為 true),其 hashCode 必相同;但不同物件 hashCode 不一定不同,若不同物件 hashCode 相同稱為衝突,會增加操作時間,故盡量定義好的 hashCode() 能加快操作。若相同物件有不同 hashCode,哈希表操作會出現意外結果(期待的 get 返回 null),避免此問題只需牢記:同時覆寫 equals 和 hashCode,而非只寫其中一個。Hashtable 是同步的。

HashMap 類

與 Hashtable 類似,不同處在於 HashMap 非同步,且允許 null(null value 和 null key)。但將 HashMap 視為 Collection 時(values() 可返回 Collection),其迭代器操作時間開銷與容量成比例。因此若迭代操作性能重要,勿將初始化容量設過高或 load factor 過低。

WeakHashMap 類

改進的 HashMap,對 key 實行「弱引用」,若 key 不再被外部引用,該 key 可被 GC 回收。

總結

  • 涉及堆疊、佇列等操作,考慮用 List;需快速插入刪除元素,用 LinkedList;需快速隨機訪問元素,用 ArrayList。
  • 單線程環境或訪問僅在一線程中,考慮非同步類,效率較高;多線程可能同時操作,應用同步類。
  • 特別注意哈希表操作,作 key 的物件要正確覆寫 equals 和 hashCode。
  • 盡量返回介面而非實際類型(如返回 List 而非 ArrayList),日後需將 ArrayList 換成 LinkedList 時,客戶端代碼無需改變,這就是針對抽象編程。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved