1. 程式人生 > >java集合set map list queue 的區別及使用場景

java集合set map list queue 的區別及使用場景



1. Java集合類基本概念

在程式設計中,常常需要集中存放多個數據。從傳統意義上講,陣列是我們的一個很好的選擇,前提是我們事先已經明確知道我們將要儲存的物件的數量。一旦在陣列初始化時指定了這個陣列長度,這個陣列長度就是不可變的,如果我們需要儲存一個可以動態增長的資料(在編譯時無法確定具體的數量),java的集合類就是一個很好的設計方案了。

集合類主要負責儲存、盛裝其他資料,因此集合類也被稱為容器類。所以的集合類都位於java.util包下,後來為了處理多執行緒環境下的併發安全問題,java5還在java.util.concurrent包下提供了一些多執行緒支援的集合類。

在學習Java中的集合類的API、程式設計原理的時候,我們一定要明白,"集合"是一個很古老的數學概念,它遠遠早於Java的出現。從數學概念的角度來理解集合能幫助我們更好的理解程式設計中什麼時候該使用什麼型別的集合類。

Java容器類類庫的用途是"儲存物件",並將其劃分為兩個不同的概念:

1) Collection
一組"對立"的元素,通常這些元素都服從某種規則
   1.1) List必須保持元素特定的順序
   1.2) Set不能有重複元素
   1.3) Queue保持一個佇列(先進先出)的順序
2) Map
一組成對的"鍵值對"物件

Collection和Map的區別在於容器中每個位置儲存的元素個數:

1) Collection 每個位置只能儲存一個元素(物件)
2) Map儲存的是"鍵值對",就像一個小型資料庫。我們可以通過""找到該鍵對應的""
1. Interface Iterable
迭代器介面,這是Collection類的父介面。實現這個Iterable介面的物件允許使用foreach進行遍歷,也就是說,所有的Collection集合物件都具有"foreach可遍歷性"。這個Iterable介面只有一個方法: iterator()。它返回一個代表當前集合物件的泛型<T>迭代器,用於之後的遍歷操作
1.1 Collection
Collection是最基本的集合介面,一個Collection代表一組Object的集合,這些Object被稱作Collection的元素。Collection是一個介面,用以提供規範定義,不能被例項化使用
    1) Set
    Set集合類似於一個罐子,"丟進"Set集合裡的多個物件之間沒有明顯的順序。Set繼承自Collection介面,不能包含有重複元素(記住,這是整個Set類層次的共有屬性)。
    Set判斷兩個物件相同不是使用"=="運算子,而是根據equals方法。也就是說,我們在加入一個新元素的時候,如果這個新元素物件和Set中已有物件進行注意equals比較都返回false,     則Set就會接受這個新元素物件,否則拒絕。
    因為Set的這個制約,在使用Set集合的時候,應該注意兩點:1) 為Set集合裡的元素的實現類實現一個有效的equals(Object)方法、2) 對Set的建構函式,傳入的Collection引數不能包  含重複的元素
        1.1) HashSet
        HashSet是Set介面的典型實現,HashSet使用HASH演算法來儲存集合中的元素,因此具有良好的存取和查詢效能。當向HashSet集合中存入一個元素時,HashSet會呼叫該物件的     hashCode()方法來得到該物件的hashCode值,然後根據該HashCode值決定該物件在HashSet中的儲存位置。
        值得主要的是,HashSet集合判斷兩個元素相等的標準是兩個物件通過equals()方法比較相等,並且兩個物件的hashCode()方法的返回值相等
            1.1.1) LinkedHashSet
            LinkedHashSet集合也是根據元素的hashCode值來決定元素的儲存位置,但和HashSet不同的是,它同時使用連結串列維護元素的次序,這樣使得元素看起來是以插入的順序儲存的。       當遍歷LinkedHashSet集合裡的元素時,LinkedHashSet將會按元素的新增順序來訪問集合裡的元素。
            LinkedHashSet需要維護元素的插入順序,因此效能略低於HashSet的效能,但在迭代訪問Set裡的全部元素時(遍歷)將有很好的效能(連結串列很適合進行遍歷)
        1.2) SortedSet    
        此介面主要用於排序操作,即實現此介面的子類都屬於排序的子類
            1.2.1) TreeSet
            TreeSet是SortedSet介面的實現類,TreeSet可以確保集合元素處於排序狀態
        1.3) EnumSet
        EnumSet是一個專門為列舉類設計的集合類,EnumSet中所有元素都必須是指定列舉型別的列舉值,該列舉型別在建立EnumSet時顯式、或隱式地指定。EnumSet的集合元素也是有序的,     它們以列舉值在Enum類內的定義順序來決定集合元素的順序
    2) List
    List集合代表一個元素有序、可重複的集合,集合中每個元素都有其對應的順序索引。List集合允許加入重複元素,因為它可以通過索引來訪問指定位置的集合元素。List集合預設按元素   的新增順序設定元素的索引
        2.1) ArrayList
        ArrayList是基於陣列實現的List類,它封裝了一個動態的增長的、允許再分配的Object[]陣列。
        2.2) Vector
        Vector和ArrayList在用法上幾乎完全相同,但由於Vector是一個古老的集合,所以Vector提供了一些方法名很長的方法,但隨著JDK1.2以後,java提供了系統的集合框架,就將     Vector改為實現List介面,統一歸入集合框架體系中
            2.2.1) Stack
            Stack是Vector提供的一個子類,用於模擬"棧"這種資料結構(LIFO後進先出)
        2.3) LinkedList
        implements List<E>, Deque<E>。實現List介面,能對它進行佇列操作,即可以根據索引來隨機訪問集合中的元素。同時它還實現Deque介面,即能將LinkedList當作雙端佇列     使用。自然也可以被當作"棧來使用"
    3) Queue
    Queue用於模擬"佇列"這種資料結構(先進先出 FIFO)。佇列的頭部儲存著佇列中存放時間最長的元素,佇列的尾部儲存著佇列中存放時間最短的元素。新元素插入(offer)到佇列的尾部,   訪問元素(poll)操作會返回佇列頭部的元素,佇列不允許隨機訪問佇列中的元素。結合生活中常見的排隊就會很好理解這個概念
        3.1) PriorityQueue
        PriorityQueue並不是一個比較標準的佇列實現,PriorityQueue儲存佇列元素的順序並不是按照加入佇列的順序,而是按照佇列元素的大小進行重新排序,這點從它的類名也可以     看出來
        3.2) Deque
        Deque介面代表一個"雙端佇列",雙端佇列可以同時從兩端來新增、刪除元素,因此Deque的實現類既可以當成佇列使用、也可以當成棧使用
            3.2.1) ArrayDeque
            是一個基於陣列的雙端佇列,和ArrayList類似,它們的底層都採用一個動態的、可重分配的Object[]陣列來儲存集合元素,當集合元素超出該陣列的容量時,系統會在底層重       新分配一個Object[]陣列來儲存集合元素
            3.2.2) LinkedList
1.2 Map
Map用於儲存具有"對映關係"的資料,因此Map集合裡儲存著兩組值,一組值用於儲存Map裡的key,另外一組值用於儲存Map裡的value。key和value都可以是任何引用型別的資料。Map的key不允許重複,即同一個Map物件的任何兩個key通過equals方法比較結果總是返回false。
關於Map,我們要從程式碼複用的角度去理解,java是先實現了Map,然後通過包裝了一個所有value都為null的Map就實現了Set集合
Map的這些實現類和子介面中key集的儲存形式和Set集合完全相同(即key不能重複)
Map的這些實現類和子介面中value集的儲存形式和List非常類似(即value可以重複、根據索引來查詢)
    1) HashMap
    和HashSet集合不能保證元素的順序一樣,HashMap也不能保證key-value對的順序。並且類似於HashSet判斷兩個key是否相等的標準也是: 兩個key通過equals()方法比較返回true、   同時兩個key的hashCode值也必須相等
        1.1) LinkedHashMap
        LinkedHashMap也使用雙向連結串列來維護key-value對的次序,該連結串列負責維護Map的迭代順序,與key-value對的插入順序一致(注意和TreeMap對所有的key-value進行排序進行區分)
    2) Hashtable
    是一個古老的Map實現類
        2.1) Properties 
        Properties物件在處理屬性檔案時特別方便(windows平臺上的.ini檔案),Properties類可以把Map物件和屬性檔案關聯起來,從而可以把Map物件中的key-value對寫入到屬性文     件中,也可以把屬性檔案中的"屬性名-屬性值"載入到Map物件中
    3) SortedMap
    正如Set介面派生出SortedSet子介面,SortedSet介面有一個TreeSet實現類一樣,Map介面也派生出一個SortedMap子介面,SortedMap介面也有一個TreeMap實現類
        3.1) TreeMap
        TreeMap就是一個紅黑樹資料結構,每個key-value對即作為紅黑樹的一個節點。TreeMap儲存key-value對(節點)時,需要根據key對節點進行排序。TreeMap可以保證所有的     key-value對處於有序狀態。同樣,TreeMap也有兩種排序方式: 自然排序、定製排序
    4) WeakHashMap
    WeakHashMap與HashMap的用法基本相似。區別在於,HashMap的key保留了對實際物件的"強引用",這意味著只要該HashMap物件不被銷燬,該HashMap所引用的物件就不會被垃圾回收。  但WeakHashMap的key只保留了對實際物件的弱引用,這意味著如果WeakHashMap物件的key所引用的物件沒有被其他強引用變數所引用,則這些key所引用的物件可能被垃圾回收,當垃  圾回收了該key所對應的實際物件之後,WeakHashMap也可能自動刪除這些key所對應的key-value對
    5) IdentityHashMap
    IdentityHashMap的實現機制與HashMap基本相似,在IdentityHashMap中,當且僅當兩個key嚴格相等(key1 == key2)時,IdentityHashMap才認為兩個key相等
    6) EnumMap
    EnumMap是一個與列舉類一起使用的Map實現,EnumMap中的所有key都必須是單個列舉類的列舉值。建立EnumMap時必須顯式或隱式指定它對應的列舉類。EnumMap根據key的自然順序  (即列舉值在列舉類中的定義順序)

3. Java集合類的應用場景程式碼

學習了集合類的基本架構框架之後,我們接著來學習它們各自的應用場景、以及細節處的注意事項

0x1: Set

HashSet

複製程式碼
import java.util.*; 

//類A的equals方法總是返回true,但沒有重寫其hashCode()方法。不能保證當前物件是HashSet中的唯一物件
class A
{
    public boolean equals(Object obj)
    {
        return true;
    }
}

//類B的hashCode()方法總是返回1,但沒有重寫其equals()方法。不能保證當前物件是HashSet中的唯一物件
class B { public int hashCode() { return 1; } } //類C的hashCode()方法總是返回2,且有重寫其equals()方法 class C { public int hashCode() { return 2; } public boolean equals(Object obj) { return true; } } public class HashSetTest { public static void main(String[] args) { HashSet books = new HashSet(); //分別向books集合中新增兩個A物件,兩個B物件,兩個C物件 books.add(new A()); books.add(new A()); books.add(new B()); books.add(new B()); books.add(new C()); books.add(new C()); System.out.println(books); } }
複製程式碼

result:

[[email protected]1, [email protected]1, [email protected]2, [email protected], [email protected]]

可以看到,如果兩個物件通過equals()方法比較返回true,但這兩個物件的hashCode()方法返回不同的hashCode值時,這將導致HashSet會把這兩個物件儲存在Hash表的不同位置,從而使物件可以新增成功,這就與Set集合的規則有些出入了。所以,我們要明確的是: equals()決定是否可以加入HashSet、而hashCode()決定存放的位置,它們兩者必須同時滿足才能允許一個新元素加入HashSet
但是要注意的是: 如果兩個物件的hashCode相同,但是它們的equlas返回值不同,HashSet會在這個位置用鏈式結構來儲存多個物件。而HashSet訪問集合元素時也是根據元素的HashCode值來快速定位的,這種鏈式結構會導致效能下降。

所以如果需要把某個類的物件儲存到HashSet集合中,我們在重寫這個類的equlas()方法和hashCode()方法時,應該儘量保證兩個物件通過equals()方法比較返回true時,它們的hashCode()方法返回值也相等

LinkedHashSet

複製程式碼
import java.util.*; 

public class LinkedHashSetTest
{
    public static void main(String[] args) 
    {
        LinkedHashSet books = new LinkedHashSet();
        books.add("Java");
        books.add("LittleHann");
        System.out.println(books);

        //刪除 Java
      books.remove("Java");
        //重新新增 Java
        books.add("Java");
        System.out.println(books);
    }
}
複製程式碼

元素的順序總是與新增順序一致,同時要明白的是,LinkedHashSetTest是HashSet的子類,因此它不允許集合元素重複

TreeSet

複製程式碼
import java.util.*;

public class TreeSetTest
{
    public static void main(String[] args) 
    {
        TreeSet nums = new TreeSet();
        //向TreeSet中新增四個Integer物件
        nums.add(5);
        nums.add(2);
        nums.add(10);
        nums.add(-9);

        //輸出集合元素,看到集合元素已經處於排序狀態
        System.out.println(nums);

        //輸出集合裡的第一個元素
        System.out.println(nums.first());

        //輸出集合裡的最後一個元素
        System.out.println(nums.last());

        //返回小於4的子集,不包含4
        System.out.println(nums.headSet(4));

        //返回大於5的子集,如果Set中包含5,子集中還包含5
        System.out.println(nums.tailSet(5));

        //返回大於等於-3,小於4的子集。
        System.out.println(nums.subSet(-3 , 4));
    }
}
複製程式碼

與HashSet集合採用hash演算法來決定元素的儲存位置不同,TreeSet採用紅黑樹的資料結構來儲存集合元素。TreeSet支援兩種排序方式: 自然排序、定製排序
1. 自然排序:

TreeSet會呼叫集合元素的compareTo(Object obj)方法來比較元素之間的大小關係,然後將集合元素按升序排序,即自然排序。如果試圖把一個物件新增到TreeSet時,則該物件的類必須實現Comparable介面,否則程式會丟擲異常。

當把一個物件加入TreeSet集合中時,TreeSet會呼叫該物件的compareTo(Object obj)方法與容器中的其他物件比較大小,然後根據紅黑樹結構找到它的儲存位置。如果兩個物件通過compareTo(Object obj)方法比較相等,新物件將無法新增到TreeSet集合中(牢記Set是不允許重複的概念)。

注意: 當需要把一個物件放入TreeSet中,重寫該物件對應類的equals()方法時,應該保證該方法與compareTo(Object obj)方法有一致的結果,即如果兩個物件通過equals()方法比較返回true時,這兩個物件通過compareTo(Object obj)方法比較結果應該也為0(即相等)

看到這裡,我們應該明白:

1) 對與Set來說,它定義了equals()為唯一性判斷的標準,而對於到了具體的實現,HashSet、TreeSet來說,它們又會有自己特有的唯一性判斷標準,只有同時滿足了才能判定為唯一性
2) 我們在操作這些集合類的時候,對和唯一性判斷有關的函式重寫要重點關注

 2. 定製排序

TreeSet的自然排序是根據集合元素的大小,TreeSet將它們以升序排序。如果我們需要實現定製排序,則可以通過Comparator介面的幫助(類似PHP中的array_map回撥處理函式的思想)。該接口裡包含一個int compare(T o1, T o2)方法,該方法用於比較大小

複製程式碼
import java.util.*;

class M
{
    int age;
    public M(int age)
    {
        this.age = age;
    }
    public String toString()
    {
        return "M[age:" + age + "]";
    }
}

public class TreeSetTest4
{
    public static void main(String[] args) 
    {
        TreeSet ts = new TreeSet(new Comparator()
        {
            //根據M物件的age屬性來決定大小
            public int compare(Object o1, Object o2)
            {
                M m1 = (M)o1;
                M m2 = (M)o2;
                return m1.age > m2.age ? -1
                    : m1.age < m2.age ? 1 : 0;
            }
        });    
        ts.add(new M(5));
        ts.add(new M(-3));
        ts.add(new M(9));
        System.out.println(ts);
    }
}
複製程式碼

看到這裡,我們需要梳理一下關於排序的概念

1) equals、compareTo決定的是怎麼比的問題,即用什麼field進行大小比較
2) 自然排序、定製排序、Comparator決定的是誰大的問題,即按什麼順序(升序、降序)進行排序
它們的關注點是不同的,一定要注意區分

EnumSet

複製程式碼
import java.util.*;

enum Season
{
    SPRING,SUMMER,FALL,WINTER
}
public class EnumSetTest
{
    public static void main(String[] args) 
    {
        //建立一個EnumSet集合,集合元素就是Season列舉類的全部列舉值
        EnumSet es1 = EnumSet.allOf(Season.class);
        //輸出[SPRING,SUMMER,FALL,WINTER]
        System.out.println(es1);

        //
            
           

相關推薦

java集合set map list queue區別使用場景

 1. Java集合類基本概念 在程式設計中,常常需要集中存放多個數據。從傳統意義上講,陣列是我們的一個很好的選擇,前提是我們事先已經明確知道我們將要儲存的物件的數量。一旦在陣列初始化時指定了這個陣列長度,這個陣列長度就是不可變的,如果我們需要儲存一個可以動態

Java集合類: SetListMapQueue區別應用

Java集合類基本概念 在程式設計中,常常需要集中存放多個數據。從傳統意義上講,陣列是我們的一個很好的選擇,前提是我們事先已經明確知道我們將要儲存的物件的數量。一旦在陣列初始化時指定了這個陣列長度,這個陣列長度就是不可變的,如果我們需要儲存一個可以動態增長

淺談java中的Set,Map,List區別

一,HashMap與Hashtable的區別 1.HashMap去掉了Hashtable 的contains方法,但是加上了containsValue()和containsKey()方法。 2.Hashtable是同步的,而HashMap是非同步的,效率上逼Hashtable要高。 3.hashMap允許空

javaset/map/list/vector 的總結

List介面對Collection進行了簡單的擴充,它的具體實現類常用的有ArrayList和LinkedList。你可以將任何東西放到一個List容器中,並在需要時從中取出。ArrayList從其命名中可以看出它是一種類似陣列的形式進行儲存,因此它的隨機訪問速度極快,而LinkedList的內部實現是連結串

Java Set集合詳解SetList區別

Java中的Set集合是繼承Collection的介面,是一個不包含重複元素的集合。     下圖是Set集合的原始碼。 Set和List都是以介面都形式來進行宣告。Set主要包含三種存放資料型別都變數,分別是HashSet,LinkedHashSet,TreeSet

Java基礎面試題3-說說你知道的幾個Java集合類:listsetqueuemap

關係這張圖簡單揭示了Set、List與Map之間的相對關係。 需要說明下的是,圖中的實現並不指這麼簡單的實現,這個稍後會說到。Collection介面Collection是Java中最基本的集合介面。它描述了一組有關集合操作的方法。int Size(); //集合大小 boo

Java集合中:ListSetmap區別和具體的使用場景和高頻問題解析

1. Interface Iterable 迭代器介面,這是Collection類的父介面。實現這個Iterable介面的物件允許使用foreach進行遍歷,也就是說,所有的Collection集合物件都具有"foreach可遍歷性"。這個Iterable介面只有一個方法: iterator()。它返回一個代

Java基礎回顧--jav集合2 Map,ListSet區別

Map 是一種把鍵物件和值物件對映的集合,它的每一個元素都包含一對鍵物件和值物件。 Map沒有繼承於Collection介面 從Map集合中檢索元素時,只要給出鍵物件,就會返回對應的值物件。  Map 的常用方法:  1 新增,刪除操作:  [html] view plain copy  

java集合類,ListSet比較,各自的子類比較(ArrayList,Vector,LinkedList;HashSet,TreeSet),Map集合比較

ArrayList,LinkedList,Vector都屬於ListList:元素是有順序的,元素可以重複因為每個元素有自己的角標(索引)|-- ArrayList:底層是陣列結構,特點是:查詢很快,增刪稍微慢點,執行緒不同步:A執行緒將元素放在索引0位置,CPU排程執行緒A停止,B執行,也將元素放在索引0位

Java集合Collection、ListSetMap使用詳解

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

Java中的Map List Set集合

Map List Set等集合類: 一、概述 在JAVA的util包中有兩個所有集合的父介面Collection和Map,它們的父子關係: +Collection 這個介面extends自 --java.lang.Iterable介面 ├+List(介面 代表有序

java集合-Set-List-Map

結構圖: 詳細好文:https://blog.csdn.net/weizhengzhou520/article/details/81806539 深度文章參考:http://www.cnblogs.com/eflylab/archive/2007/01/19/625086.html

JAVA集合框架之ListMapSet之間的選擇~小案例分析

案例分析 案例介紹:簡易撲克牌遊戲。 功能描述: 二:實現洗牌 三:實現發牌 四:得出輸贏 集合(list、set、map)的選擇 既然要比較,我們還是先從JAVA集合的祖先來介紹。 陣列 時間本沒有集合,但有人想要,所以有了集合

Java基礎面試題3-說說你知道的幾個Java集合類:listsetmap

關係 這張圖簡單揭示了Set、List與Map之間的相對關係。  需要說明下的是,圖中的實現並不指這麼簡單的實現,這個稍後會說到。 Collection介面 Collection是Java中最基本的集合介面。它描述了一組有關集合操作的方法。 int Size(); /

【夯實基礎】JAVA集合框架總結(listset區別等等)

幾個面試常見問題: 1.Q:ArrayList和Vector有什麼區別?HashMap和HashTable有什麼區別?   A:Vector和HashTable是執行緒同步的(synchronized)。效能上,ArrayList和HashMap分別比Vector和Hashtable要好。 2.Q:大致講解j

Java集合整理(List and Set and Map

集合的由來 陣列長度是固定,當新增的元素超過了陣列的長度時需要對陣列重新定義,太麻煩,java內部給我們提供了集合類,能儲存任意物件,長度是可以改變的,隨著元素的增加而增加,隨著元素的減少而減少 陣列和集合的區別 區別1 : 陣列既可以儲存基本資

JAVA集合 Set(集)、List(列表)、Map(對映)、Collection(介面)

對JAVA集合的理解:     JAVA集合可以儲存和運算元目不固定的一組資料;     它不同於陣列,陣列的大小是固定的,並且只能存放型別相同的資料(基本型別/引用型別);     所有的JAVA集合都存放在java.util包中;     JAVA集合只能存放引用型別的

Java 集合基礎知識 List/Set/Map

linked 想要 n) nod java 集合 不同 factor inf 優化 一、List Set 區別 List 有序,可重復; Set 無序,不重復; 二、List Set 實現類間區別及原理 Arraylist 底層實現使用Obje

Java集合SetMap、HashSet、HashMap、TreeSet、TreeMap等

程序 對待 tro value treeset mov str ble collect 1、Set和Map的關系: Set代表一種集合元素無序、不可重復的集合,Map代表一種由多個key-value對組成的集合。 Set的集合繼承體系: Map關系集合 Map

Hashmap,Set,Map,List,ArrayList的區別

安全 列表 jdk1 bsp 固定 syn 實現 是否 並且                   表格: 類型 默認容量 加載因子[1] 擴容增量 底層實現 是否安全及同步方式 Vecto