1. 程式人生 > >Collection,List,Set和Map用法和區別

Collection,List,Set和Map用法和區別

Collection List Set Map 用法和區別

作者: zccst

Java spring MVC 框架的呼叫關係是弄明白了,可是發現後面要走的路還很長,有很多東西對我還是很神祕,比如 list set map 等,今天就來一一解開他們的面紗。當還還有一大堆需要記憶的系統已經封裝好的類、介面等等,這些內容會在以後,慢慢道來。

首先看一下他們之間的關係

Collection 介面的介面 物件的集合 List 子介面 按進入先後有序儲存 可重複 │├ LinkedList 介面實現類 連結串列 插入刪除 沒有同步

執行緒不安全 │├ ArrayList 介面實現類 陣列 隨機訪問 沒有同步 執行緒不安全 │└ Vector 介面實現類 陣列 同步 執行緒安全 Stack
Set 子介面 僅接收一次,並做內部排序

HashSet

LinkedHashSet
TreeSet

對於 List ,關心的是順序, 它保證維護元素特定的順序(允許有相同元素),使用此介面能夠精確的控制每個元素插入的位置。使用者能夠使用索引(元素在 List 中的位置,類似於陣列下標)來訪問 List 中的元素。

對於 Set ,只關心某元素是否屬於 Set

(不 允許有相同元素 ),而不關心它的順序。

Map 介面 鍵值對的集合 Hashtable 介面實現類 同步 執行緒安全 HashMap 介面實現類 沒有同步 執行緒不安全

│├ LinkedHashMap

│└ WeakHashMap

TreeMap
IdentifyHashMap

對於 Map ,最大的特點是鍵值對映,且為一一對映,鍵不能重複,值可以,所以是用鍵來索引值。 方法 put(Object key, Object value) 新增一個“值” ( 想要得東西 ) 和與“值”相關聯的“鍵” (key) ( 使用它來查詢 ) 。方法

get(Object key) 返回與給定“鍵”相關聯的“值”。

Map 同樣對每個元素儲存一份,但這是基於 " " 的, Map 也有內建的排序,因而不關心元素新增的順序。如果新增元素的順序對你很重要,應該使用 LinkedHashSet 或者 LinkedHashMap.

對於效率, Map 由於採用了雜湊雜湊,查詢元素時明顯比 ArrayList 快。

但我有一個自己的原則想法:複雜的問題簡單化。即把很多晦澀難懂的問題用通俗直白的話,一下子就看明白了,而不是大段大段的寫。不得不指出的是現在部分所謂的“專家”往往把簡單的問題複雜化,讓人看了生畏,甚至望而卻步,以此來顯示他的高深莫測,當然也可能有別的用意,那我就不得而知了。

更為精煉的總結:

Collection 是物件集合, Collection 有兩個子介面 List Set

List 可以通過下標 (1,2..) 來取得值,值可以重複

Set 只能通過遊標來取值,並且值是不能重複的

ArrayList Vector LinkedList List 的實現類

ArrayList 是執行緒不安全的, Vector 是執行緒安全的,這兩個類底層都是由陣列實現的

LinkedList 是執行緒不安全的,底層是由連結串列實現的

Map 是鍵值對集合

HashTable HashMap Map 的實現類  
HashTable
是執行緒安全的,不能儲存 null  
HashMap
不是執行緒安全的,可以儲存 null

所以,如果你是想在一個很短的時間來弄明白這些問題,比如 1~2 分鐘。沒有也不想花大量時間於此,那麼建議你現在就可以收兵走人了。

如果你想對此做一個詳細的瞭解,請繼續看下去。

眾所周知, Java 來源於 C++ ,遮蔽了其底層實現,簡化了對底層實現的管理,使開發者專注於上層功能的實現。在 C/C++ 裡關於資料的儲存需要程式設計師非常清楚,而 Java 程式設計師可以完全不管這些,那麼, Java 是怎麼管理的呢?其實 Java 還是需要面臨這些問題,只不過經過封裝後,變得面目全非。所以對於像我這種從 C/C++ 轉向 Java 的人還需要一段時間適應, Collection List Set Map 等概念還需要一個接受的過程。其實到後來發現,不管是什麼語言,其底層儲存不外乎陣列、線性表、棧、佇列、串、樹和圖等資料結構。想明白了這些,一切都敞亮了。

一、容器( Collection 介面  容器( Collection )是最基本的集合介面,一個容器( Collection )儲存一組物件( Object ),即物件是容器的元素( Elements )。一些 Collection 允許相同的元素而另一些不行。一些能排序而另一些不行。 Java SDK 不提供直接繼承自 Collection 的類, Java SDK 提供的類都是繼承自 Collection 子介面 List Set   所有實現 Collection 介面的類都必須提供兩個標準的建構函式:無引數的建構函式用於建立一個空的 Collection ,有一個 Collection 引數的建構函式用於建立一個新的 Collection ,這個新的 Collection 與傳入的 Collection 有相同的元素。後一個建構函式允許使用者複製一個 Collection   如何遍歷 Collection 中的每一個元素?不論 Collection 的實際型別如何,它都支援一個 iterator() 的方法,該方法返回一個迭代子,使用該迭代子即可逐一訪問 Collection 中每一個元素。典型的用法如下: Iterator it = collection.iterator(); // 獲得一個迭代子 while(it.hasNext()) {
Object obj = it.next(); // 得到下一個元素 }

Collection 介面派生的兩個介面是 List Set List 按物件進入的順序儲存物件,不做排序或編輯操作。 Set 對每個物件只接受一次,並使用自己內部的排序方法 ( 通常,你只關心某個元素是否屬於 Set, 而不關心它的順序 -- 否則應該使用 List)

1 List 介面 List 是有序的 Collection ,次序是 List 最重要的特點:它保證維護元素特定的順序。使用此介面能夠精確的控制每個元素插入的位置。使用者能夠使用索引(元素在 List 中的位置,類似於陣列下標)來訪問 List 中的元素,這類似於 Java 的陣列。和下面要提到的 Set 不同, List 允許有相同的元素。  除了具有 Collection 介面必備的 iterator() 方法外, List 還提供一個 listIterator() 方法,返回一個 ListIterator 介面,和標準的 Iterator 介面相比, ListIterator 多了一些 add() 之類的方法,允許新增,刪除,設定元素, 還能向前或向後遍歷。   實現 List 介面的常用類有 LinkedList ArrayList Vector Stack 。其中,最常用的是 LinkedList ArrayList 兩個。

LinkedList
LinkedList 實現了 List 介面,允許 null 元素。此外 LinkedList 提供額外的 addFirst(), addLast(), getFirst(), getLast(), removeFirst(), removeLast(), insertFirst(), insertLast() 方法在 LinkedList 的首部或尾部,這些方法(沒有在任何介面或基類中定義過)使 LinkedList 可被用作堆疊( stack ),佇列( queue )或雙向佇列( deque )。

注意 LinkedList 沒有同步方法。如果多個執行緒同時訪問一個 List ,則必須自己實現訪問同步。一種解決方法是在建立 List 時構造一個同步的 List List list = Collections.synchronizedList(new LinkedList(...));

特點:對順序訪問進行了優化,向 List 中間插入與刪除的開銷並不大。隨機訪問則相對較慢。 ( 使用 ArrayList 代替。 )

ArrayList
ArrayList 是由陣列實現的 List ,並且實現了可變大小的陣列。它允許所有元素,包括 null ArrayList 沒有同步。 size isEmpty get set 方法執行時間為常數。但是 add 方法開銷為分攤的常數,新增 n 個元素需要 O(n) 的時間。其他的方法執行時間為線性。  每個 ArrayList 例項都有一個容量( Capacity ),即用於儲存元素的陣列的大小。這個容量可隨著不斷新增新元素而自動增加,但是增長演算法並沒有定義。當需要插入大量元素時,在插入前可以呼叫 ensureCapacity 方法來增加 ArrayList 的容量以提高插入效率。   和 LinkedList 一樣, ArrayList 也是非同步的( unsynchronized )。

特點:允許對元素進行快速隨機訪問,但是向 List 中間插入與移除元素的速度很慢。 ListIterator 只應該用來由後向前遍歷 ArrayList, 而不是用來插入和移除元素。因為那比 LinkedList 開銷要大很多。

Vector Vector 非常類似 ArrayList ,但是 Vector 是同步的。由 Vector 建立的 Iterator ,雖然和 ArrayList 建立的 Iterator 是同一介面,但是,因為 Vector 是同步的,當一個 Iterator 被建立而且正在被使用,另一個執行緒改變了 Vector 的狀態(例如,新增或刪除了一些元素),這時呼叫 Iterator 的方法時將丟擲 ConcurrentModificationException ,因此必須捕獲該異常。

Stack
類: Stack 繼承自 Vector ,實現一個後進先出的堆疊。 Stack 提供 5 個額外的方法使得 Vector 得以被當作堆疊使用。基本的 push pop 方法,還有 peek 方法得到棧頂的元素, empty 方法測試堆疊是否為空, search 方法檢測一個元素在堆疊中的位置。 Stack 剛建立後是空棧。 2 Set 介面 Set 具有與 Collection 完全一樣的介面,因此沒有任何額外的功能,不像前面有幾個不同的 List 。實際上 Set 就是 Collection ,只是行為不同。(這是繼承與多型思想的典型應用:表現不同的行為)。其次, Set 是一種不包含重複的元素的 Collection ,加入 Set 的元素必須定義 equals() 方法以確保物件的唯一性 即任意的兩個元素 e1 e2 都有 e1.equals(e2)=false ),與 List 不同的是, Set 介面不保證維護元素的次序。最後, Set 最多有一個 null 元素。   很明顯, Set 的建構函式有一個約束條件,傳入的 Collection 引數不能包含重複的元素。   請注意:必須小心操作可變物件( Mutable Object )。如果一個 Set 中的可變元素改變了自身狀態導致 Object.equals(Object)=true 將導致一些問題。

HashSet

為快速查詢設計的 Set 。存入 HashSet 的物件必須定義 hashCode()

LinkedHashSet 類:具有 HashSet 的查詢速度,且內部使用連結串列維護元素的順序 ( 插入的次序 ) 。於是在使用迭代器遍歷 Set 時,結果會按元素插入的次序顯示。

TreeSet

儲存次序的 Set, 底層為樹結構。使用它可以從 Set 中提取有序的序列。

二、 Map 介面  請注意, Map 沒有繼承 Collection 介面, Map 提供 key value 的對映,你可以通過“鍵”查詢“值”。一個 Map 中不能包含相同的 key ,每個 key 只能對映一個 value Map 介面提供 3 種集合的檢視, Map 的內容可以被當作一組 key 集合,一組 value 集合,或者一組 key-value 對映。

方法 put(Object key, Object value) 新增一個“值” ( 想要得東西 ) 和與“值”相關聯的“鍵” (key) ( 使用它來查詢 ) 。方法 get(Object key) 返回與給定“鍵”相關聯的“值”。可以用 containsKey() containsValue() 測試 Map 中是否包含某個“鍵”或“值”。 標準的 Java 類庫中包含了幾種不同的 Map HashMap, TreeMap, LinkedHashMap, WeakHashMap, IdentityHashMap 。它們都有同樣的基本介面 Map ,但是行為、效率、排序策略、儲存物件的生命週期和判定“鍵”等價的策略等各不相同。

Map 同樣對每個元素儲存一份,但這是基於 " " 的, Map 也有內建的排序,因而不關心元素新增的順序。如果新增元素的順序對你很重要,應該使用 LinkedHashSet 或者 LinkedHashMap.

執行效率是 Map 的一個大問題。看看 get() 要做哪些事,就會明白為什麼在 ArrayList 中搜索“鍵”是相當慢的。而這正是 HashMap 提高速度的地方。 HashMap 使用了特殊的值,稱為“雜湊碼” (hash code) ,來取代對鍵的緩慢搜尋。“雜湊碼”是“相對唯一”用以代表物件的 int 值,它是通過將該物件的某些資訊進行轉換而生成的(在下面總結二:需要的注意的地方有更進一步探討)。所有 Java 物件都能產生雜湊碼,因為 hashCode() 是定義在基類 Object 中的方法 HashMap 就是使用物件的 hashCode() 進行快速查詢的。此方法能夠顯著提高效能。


Hashtable
Hashtable 繼承 Map 介面,實現一個 key-value 對映的雜湊表。任何非空( non-null )的物件都可作為 key 或者 value   新增資料使用 put(key, value) ,取出資料使用 get(key) ,這兩個基本操作的時間開銷為常數。
Hashtable
通過初始化容量 (initial capacity) 和負載因子 (load factor) 兩個引數調整效能。通常預設的 load factor 0.75 較好地實現了時間和空間的均衡。增大 load factor 可以節省空間但相應的查詢時間將增大,這會影響像 get put 這樣的操作。 使用 Hashtable 的簡單示例如下,將 1 2 3 放到 Hashtable 中,他們的 key 分別是 ”one” ”two” ”three” Hashtable numbers = new Hashtable();
numbers.put(“one”, new Integer(1));
numbers.put(“two”, new Integer(2));
numbers.put(“three”, new Integer(3));
  要取出一個數,比如 2 ,用相應的 key Integer n = (Integer)numbers.get(“two”);
System.out.println(“two = ” + n);
 由於作為 key 的物件將通過計算其雜湊函式來確定與之對應的 value 的位置,因此任何作為 key 的物件都必須實現 hashCode 方法和 equals 方法。 hashCode 方法和 equals 方法繼承自根類 Object ,如果你用自定義的類當作 key 的話,要相當小心,按照雜湊函式的定義,如果兩個物件相同,即 obj1.equals(obj2)=true ,則它們的 hashCode 必須相同,但如果兩個物件不同,則它們的 hashCode 不一定不同,如果兩個不同物件的 hashCode 相同,這種現象稱為衝突,衝突會導致操作雜湊表的時間開銷增大,所以儘量定義好的 hashCode() 方法,能加快雜湊表的操作。   如果相同的物件有不同的 hashCode ,對雜湊表的操作會出現意想不到的結果(期待的 get 方法返回 null ),要避免這種問題,只需要牢記一條:要同時複寫 equals 方法和 hashCode 方法,而不要只寫其中一個。 Hashtable 是同步的。

HashMap
HashMap Hashtable 類似,也是基於散列表的實現。不同之處在於 HashMap 是非同步的,並且允許 null ,即 null value null key 。將 HashMap 視為 Collection 時( values() 方法可返回 Collection ),插入和查詢“鍵值對”的開銷是固定的,但其迭代子操作時間開銷和 HashMap 的容量成比例。因此,如果迭代操作的效能相當重要的話,不要將 HashMap 的初始化容量 (initial capacity) 設得過高,或者負載因子 (load factor) 過低。

LinkedHashMap 類:類似於 HashMap ,但是迭代遍歷它時,取得“鍵值對”的順序是其插入次序,或者是最近最少使用 (LRU) 的次序。只比 HashMap 慢一點。而在迭代訪問時發而更快,因為它使用連結串列維護內部次序。

WeakHashMap 類:弱鍵( weak key Map 是一種改進的 HashMap ,它是為解決特殊問題設計的,對 key 實行 弱引用 ,如果一個 key 不再被外部所引用(沒有 map 之外的引用),那麼該 key 可以被垃圾收集器 (GC) 回收。

TreeMap

基於紅黑樹資料結構的實現。檢視“鍵”或“鍵值對”時,它們會被排序 ( 次序由 Comparabel Comparator 決定 ) TreeMap 的特點在於,你得到的結果是經過排序的。 TreeMap 是唯一的帶有 subMap() 方法的 Map ,它可以返回一個子樹。

IdentifyHashMap

使用 == 代替 equals() 對“鍵”作比較的 hash map 。專為解決特殊問題而設計。

總結一:比較

1 ,陣列 (Array) ,陣列類 (Arrays)

Java 所有“儲存及隨機訪問一連串物件”的做法, array 是最有效率的一種。但缺點是容量固定且無法動態改變。 array 還有一個缺點是,無法判斷其中實際存有多少元素, length 只是告訴我們 array 的容量。

Java 中有一個數組類 (Arrays) ,專門用來操作 array 。陣列類 (arrays) 中擁有一組 static 函式。

equals() :比較兩個 array 是否相等。 array 擁有相同元素個數,且所有對應元素兩兩相等。

fill() :將值填入 array 中。

sort() :用來對 array 進行排序。

binarySearch() :在排好序的 array 中尋找元素。

System.arraycopy() array 的複製。

若編寫程式時不知道究竟需要多少物件,需要在空間不足時自動擴增容量,則需要使用容器類庫, array 不適用。

2 ,容器類與陣列的區別

容器類僅能持有物件引用(指向物件的指標),而不是將物件資訊 copy 一份至數列某位置。一旦將物件置入容器內,便損失了該物件的型別資訊。

3 ,容器 (Collection) Map 的聯絡與區別

Collection 型別,每個位置只有一個元素。

Map 型別,持有 key-value (pair) ,像個小型資料庫。

Collections 是針對集合類的一個幫助類。提供了一系列靜態方法實現對各種集合的搜尋、排序、執行緒完全化等操作。相當於對 Array 進行類似操作的類—— Arrays

如, Collections.max(Collection coll); coll 中最大的元素。

Collections.sort(List list); list 中元素排序

List Set Map 將持有物件一律視為 Object 型別。

Collection List Set Map 都是介面,不能例項化。繼承自它們的 ArrayList, Vector, HashTable, HashMap 是具象 class ,這些才可被例項化。

vector 容器確切知道它所持有的物件隸屬什麼型別。 vector 不進行邊界檢查。

總結二:需要注意的地方

1 Collection 只能通過 iterator() 遍歷元素,沒有 get() 方法來取得某個元素。

2 Set Collection 擁有一模一樣的介面。但排除掉傳入的 Collection 引數重複的元素。

3 List ,可以通過 get() 方法來一次取出一個元素。使用數字來選擇一堆物件中的一個, get(0)... (add/get)

4 Map put(k,v) / get(k) ,還可以使用 containsKey()/containsValue() 來檢查其中是否含有某個 key/value

HashMap

相關推薦

CollectionListSetMap用法區別

Collection , List , Set 和 Map 用法和區別 作者: zccst Java spring MVC 框架的呼叫關係是弄明白了,可是發現後面要走的路還很長,有很多東西對我還是很神祕,比如 list , set , map 等,

常用JAVA集合框架(CollectionListSetMap

注意,此實現不是同步的。如果多個執行緒同時訪問一個 ArrayList 例項,而其中至少一個執行緒從結構上修改了列表,那麼它必須 保持外部同步。(結構上的修改是指任何新增或刪除一個或多個元素的操作,或者顯式調整底層陣列的大小;僅僅設定元素的值不是結構上的修改。)應該使用 Collections.synchro

Java集合CollectionListSetMap使用詳解

Java集合排序及java集合類詳解 (Collection, List, Set, Map) 摘要內容 集合是Java裡面最常用的,也是最重要的一部分。能夠用好集合和理解好集合對於做Java程式的開發擁有無比的好處。本文詳細解釋了關於Java中的集合是如何實現

CollectionListSetMap關係圖學習筆記1

用PD畫了一張相關介面、相關類及主要方法的圖 幫助加深理解與記憶 接著對主要類 做了個簡單的測試 更多的測試與學習 後續後補上 /** * */ package com.undergrowth.util; import java.util.ArrayLis

jav核心(十四):集合類型操作:CollectionListSetMap集合;Iterator叠代器

equal exc ron 添加 推出 使用 映射關系 不同的 stat 一、java.util.List 1、List總結 List中允許保存重復的數據; List中允許保存多個null; 常用實現類:ArrayList【推薦使用】、Vector、Linked

Java中 ListSetMap 之間的區別

  小博此篇記錄了開發過程中常用的幾種集合詳解,三者的區別對比均從IDEA相關層次圖裡面所得知,基於JDK8,如有錯誤歡迎批評指正。 List(列表)   List的元素以線性方式儲存,可以存放

總結for循環及for循環增強遍歷數組listsetmap

循環 string 沒有 htable str arr val aaa entry 一.對於集合 (1)普通for循環 int[] arr = { 2, 1, 2 }; for(int i=0;i<arr.length;i++){

簡單說一下SetlistMap的型別自己的特點

首先是Set,List,Map Set和list都是繼承了Conllection介面,而Map是本身就是一個介面 set是最簡單的一種集合,沒有重複物件 set介面主要有兩個實現:     1,hashSet:hashSet按照雜湊演算法進行存取集合中的物件,有hashcode(),存取速度比較快

關於java裡面Collection包括ListMap等初始化內部匿名類泛型的一個例子

package com.yang.generalType; import java.util.ArrayList; import java.util.List; public class TestGeneralType { /** * @param args

Java基礎及提高 之 陣列ListSetMap的幾種遍歷方式

一,陣列的遍歷方式 陣列有兩種遍歷方式: public class ArrayXunhuan { public static void main(String[] args) { int[

(一)jdk原始碼分析之collectionListSet

前言 標題取得有點大,一口氣分析三塊的原始碼,看上去是個很大的話題,不過在個人看來,一方面,這三個都是介面,不涉及程式碼實現,讀起來比較快,另一方面,大家都知道List,Set這兩個介面都繼承自collection,他們之間存在關聯,所以放在一塊分析討論最能凸顯,這三塊介面

collection介面(listsetmap介面的區別

collection Collection是最基本的集合介面,聲明瞭適用於JAVA集合(只包括Set和List)的通用方法。Map介面並不是Collection介面的子介面,但是它仍然被看作是Collection框架的一部分。 list List的長度可變

Java中的ListMap有什麼區別List, Set, Map是否繼承自Collection介面?

List,Set,Map是否繼承自Collection介面?  答:List,Set是,Map不是。 Collection是最基本的集合介面,一個Collection代表一組Object,即Collection的元素。一些Collection允許相同的元素而另一些不行。一

在spring 中如何注入mapsetlistproperty等引數

package cn.dao;   publicinterface PersonDao {       publicabstractvoid add();   }   cn.dao.imp package cn.d

陣列jsonListMap的初始化、取值遍歷記錄

1、陣列 /*  * @author willon  * 陣列遍歷demo  * 陣列的初始化必須有固定長度  */ public class ArraytraversalDemo {public static void main(String[] args) { //未賦

SetListMap

Set(集) List(列表) Map(對映) List特點:元素有放入順序,元素可重複 Map特點:元素按鍵值對儲存,無放入順序 Set特點:元素無放入順序,元素不可重複(注意:元素雖然無放入順序,但是元素在set中的位置是有該元素的HashCode決定的,其位置其實是固定的)

1.24 集合對映(setlistmap的使用)

一、在一對多關係中,“一”方要加入變數儲存多方資訊。可以用set和list實現。一般用set,少數用list(物件需要排序時用list) @Entity @Table(name="t_group") public class Group {private int id;pr

Scala之ArrayList,Tuple,Set,Map

package com.scala.study /** * Created by Administrator on 2016/8/8. */ object Test { def max(x:Int,y:Int):Int={ if(x&g

C++各個容器比較(vectordequelistsetmapqueuestack)

1、vector(連續的空間儲存,可以使用[ ]操作符)可以快速的訪問隨機的元素,快速的在末尾插入元素,但是在序列中間隨機的插入、刪除元素要慢。而且,如果一開始分配的空間不夠時,有一個重新分配更大空間的過程。 2、deque(小片的連續,小片間用連結串列相連,實際上內部有一

Scala筆記(一):ArrayListTupleSetMapIterator

1. 陣列(Array) 陣列是程式設計中經常用到的資料結構,Scala中包括定長陣列(Array)和變長陣列(ArrayBuffer)。 定長陣列,就是長度不變的陣列,在Scala中使用Array進行宣告,如下: val intArr = new A