1. 程式人生 > >工作隨筆—Java容器基礎知識分享(持有對象)

工作隨筆—Java容器基礎知識分享(持有對象)

客戶端 概述 普通 用途 不同 劃分 承諾 apt 自動調整

1. 概述
  通常,程序總是運行時才知道的根據某些條件去創建新對象。在此之前,不會知道所需對象的數量,甚至不知道確切的類型,為解決這個普遍的編程問題:需要在任意時刻和任意位置創建任意數量的對象,所以,就不能依靠創建命名的引用來持有每一個對象,因為你不知道實際上會需要多少這樣的引用。
  大多數語言都提供某種方法來解決這個基本問題。Java有多種方式保存對象(應該說是對象的引用)。例如數組,它是編譯器支持的類型。數組是保存一組對象的最有效的方式,如果你想保存一組基本類型數據,也推薦使用這種方式。但是數據具有固定的尺寸,而在更一般的情況中,你在寫程序時並不知道將需要多少個對象,或者是否需要更復雜的方式來存儲對象,因此數組尺寸固定這一限制就顯得過於受限了。


  所以Java實用類庫提供了一套相當完整的容器類來解決這個問題,其中基本的類型是List、Set、Queue和Map。這些對象類型也稱為集合類,但由於Java的類庫中使用了Collection這個名字來指代該類庫的一個特殊子集,所以我使用了範圍更廣的術語“容器”稱呼他們。

2. 基本概覽
  Java容器類類庫的用途是“保存對象”,並將其劃分為兩個不同的概念:
  1)Collection:一個獨立元素的序列,這些元素都服從一條或多條規則。List必須按照插入的順序保存元素,而Set不能有重復元素。Queue按照排隊規則來確定對象產生的順序(通常與它們被插入的順序相同)。


  2)Map:一組成對的“鍵值對”對象,允許你使用鍵來查找值。ArrayList允許你使用數字來查找值,因此在某種意義上講,它將數字與對象關聯在一起。映射表允許我們使用另外一個對象來查找某個對象,它也被稱為“關聯數組”,因為它將某些對象與另外一些對象關聯在了一起;或者被稱為“字典”,因為你可以使用鍵對象來查找對象,就像在字典中使用單詞來定義一樣。

3. List
  List承諾可以將元素維護在特定的序列中。List接口在 Collection的基礎上添加了大量的方法,使得可以在List的中間插入和移除元素。
  有兩種類型的List:


  1)基本的 Arraylist,它長於隨機訪問元素,但是在List的中間插入和移除元素時較慢。
  2)LinkedList,它通過代價較低的在List中間進行插入和刪除操作,提供了優化的順序訪問。 LinkedList在隨機訪問方面相對比較慢,但是它的特性集較 ArrayList更大。

4. 叠代器
  叠代器(一種設計模式)的概念可以用於不重寫代碼就可以應用於不同類型的容器。叠代器是一個對象,它的工作是遍歷並選擇序列中的對象,而客戶端程序員不必知道或關心該序列底層的結構。此外,選代器通常被稱為輕量級對象:創建它的代價小。因此,經常可以見到對叠代器有些奇怪的限制
  例如,Java的 Iterator只能單向移動,這個 Iterator只能用來:
  1)使用方法 iterator()要求容器返回一個 Iterator。 Iterator將準備好返回序列的第一個元素。
  2)使用next()獲得序列中的下一個元素。
  3)使用 hashNext()檢查序列中是否還有元素。
  4)使用 remove()將叠代器新近返回的元素刪除。

5. LinkedList
  LinkedLlist也像 ArrayListー樣實現了基本的List接ロ,但是它執行某些操作(在List的中間插入和移除)時比 ArrayList更高效,但在隨機訪問操作方面卻要遜色一些。
  LinkedList還添加了可以使其用作棧、隊列或雙端隊列的方法。
  這些方法中有些彼此之間只是名稱有些差異,或者只存在些許差異,以使得這些名字在特定用法的上下文環境中更加適用(特別是在 Queuer中)。例如, getFirst()和 element()完全一樣,它們都返回列表的頭(第一個元素),而並不移除它,如果List為空,則拋出 NoSuchElementException。peek()方法與這兩個方式只是稍有差異,它在列表為空時返回null。
  removeFirst()與remove()也是完全一樣的,它們移除並返回列表的頭,而在列表為空時拋出NoSucheElementException。
  poll()稍有差異,它在列表為空時返回null。
  addFirst()與add()和 addLast()相同,它們都將某個元素插入到列表的尾(端)部
  removeLast()移除並返回列表的最後一個元素。

6. Stack
  “棧”通常是指“後進先出”(LIFO)容器。有時棧也被稱為疊加棧,因為最後“壓入”棧的元素,第一個“彈出”棧。經常用來類比棧的事物是裝有彈簧的儲物器的自助餐托盤,最後裝入的托盤總是最先拿出使用。

7. Set
  Set不保存重復的元素。如果你試圖將相同對象的多個實例添加到Set中,那麽它就會阻止這種重復現象。Set中最常被使用的是測試歸屬性,你可以很容易地詢問某個對象是否在某個Set中。正因如此,查找就成為了Set中最重要的操作,因此你通常都會選擇一個 HashSet的實現,它專門對快速查找進行了優化。
  Set具有與 Collection完全一樣的接口,因此沒有任何額外的功能,不像前面有兩個不同的List。實際上Set就是 Collection,只是行為不同。(這是繼承與多態思想的典型應用:表現不同的行為)

8. Queue
  隊列是一個典型的先進先出(FIFO)的 容器。即從容器的一端放入事物,從另一端取出,並且事物放入容器的順序與取出的順序是相同的。隊列常被當做一種可靠的將對象從程序的某個區域傳輸到另一個區域的途徑。

9. 總結
  Java提供了大量持有對象的方式:
  1)數組將數字與對象聯系起來。它保存類型明確的對象,查詢對象時,不需要對結果做類型轉換。它可以是多維的、可以保存基本類型的數據。但是,數組一且生成,其容量就不能改變。
  2) Collection保存單一的元素,而Map保存相關聯的鍵值對。有了Java的泛型,你就可以指定容器中存放的對象類型,因此你就不會將錯誤類型的對象放置到容器中,並且在從容器中獲取元素時,不必進行類型轉換。各種 Collection和各種Map都可以在你向其中添加更多的元素時,自動調整其尺寸。容器不能持有基本類型,但是自動包裝機制會仔細地執行基本類型到容器中
所持有的包裝器類型之間的雙向轉換。
  3)像數組一樣,List也建立數字索引與對象的關聯,因此,數組和List都是排好序的容器。List能夠自動擴充容量。
  4)如果要進行大量的隨機訪問,就使用 ArrayList;如果要經常從表中間插入或刪除元素,則該使用 LinkedList。
  5)各種 Queue以及棧的行為,由 LinkedList提供支持。
  6)Map是一種將對象(而非數字)與對象相關聯的設計。 HashMap設計用來快速訪問。而Treemapf保持“鍵”始終處於排序狀態,所以沒有 Hashmapt快。 LinkedMap保持元素插人的順序,但是也通過散列提供了快速訪問能力。
  7)Set不接受重復元素。 HashSet提供最快的查詢速度,而 TreeSet保持元素處於排序狀態,LinkedHashSet以插入順序保存元素。
  8)新程序中不應該使用過時的 Vector、 Hashtable和 Stack。
  瀏覽一下Java容器的簡圖(不包含抽象類和遺留構件)會大有裨益。這裏只包含你在一般情況下會碰到的接口和類。

技術分享圖片

  你可以看到,其實只有四種容器:Map、List、Set和 Queue,它們各有兩到三個實現版本( Queue的java.util.concurrent實現沒有包括在上面這張圖中)。常用的容器用黑色粗線框表示。
  點線框表示接口,實線框表示普通的(具體的)類。帶有空心箭頭的點線表示一個特定的類實現了一個接口,實心箭頭表示某個類可以生成箭頭所指向類的對象。例如,任意的Collection可以生成 Iterator,而List可以生成 ListIterator(也能生成普通的 Iterator,因為List繼承自 Collection)。

工作隨筆—Java容器基礎知識分享(持有對象)