[Java基礎篇]對Java中的集合相關知識點的剖析

一、瞭解一些集合類的基本概念

我們以前都已經學過了數組了,我們來回憶以下:數組一旦初始化就指定看數組長度,如果數組需要保存數量變化的數據,數組就顯得無能爲力了。而且數組也無法保存具有映射關係的數據。如:成績表:語文-79。
爲了保存數量不確定的數據,以及保存具有映射關係的數據(關聯數組),Java提供了集合類。集合類主要負責保存、盛裝其他數據,因此集合類也被稱爲容器類。Java所有的集合類都位於java.util包下,提供了一個表示和操作對象集合的統一框架,包含大量集合接口,以及這些接口的實現類和操作它們的算法。
集合類和數組在保存的數據元素上面的不同:數組元素既可以是基本類型,也可以是對象(實際上保存的是對象引用變量)。二集合裏只能保存對象(實際上只是保存對象的引用變量,但習慣認爲集合裏保存的是對象)。

1.1 Java集合框架的接口

在這裏插入圖片描述

1.2 Java庫中的具體集合

集合類型 描述
ArrayList 一種可以動態增長和縮減的索引序列
LinkedList 一種可以在任何位置進行高效地插入和刪除操作的有序序列
ArrayDeque 一種循環數組實現的雙端隊列
HashSet 一種沒有重複元素的無序集合
TreeSet 一種有序集
EnumSet 一種包含枚舉類型值的集
LinkedHashSet 一種可以記住元素插入次序的集
PriorityQueue 一種允許高效刪除最小元素的集合
HashMap 一種存儲鍵/值關聯的數據結構
TreeMap 一種鍵值有序排列的映射表
EnumMap 一種鍵值屬於枚舉類型的映射表
LinkedHashMap 一種記住鍵/值項添加次序的映射表
WeakHashMap 一種其值無用武之地後可以被垃圾回收期回收的映射表
IdentityHashMap 一種用==而不是用equals比較鍵值的映射表

在這裏插入圖片描述
在這裏插入圖片描述
在上面的圖中我們可以看到很多以“Abstract”開頭的容器,其實它們只是部分實現某個特定接口的簡單工具而已。如:我們如果要製作自己的Set的話,一般不會直接繼承Set接口,然後實現所有的方法。而是應該繼承AbstractSet,只爲自己的新類作最必要的工作。不過,容器類類庫已經包含足夠的功能來滿足你的需要了。所以,對我們而言,可以忽略那些以“Abstract”開頭的類。
*☞ 注意:所有的Collection都能通過iterator()方法生成Iterator。

☞ 容器的缺點:未知類型
容器只保存Object型的引用,這是所有類的基類,因此容器可以保存任何類型的對象。不過:

  1. 因爲在你將對象的引用加入容器就丟失了類型的信息,所以對於添加容器的對象沒有類型限制,即使你刻意保持容器的類型。例如類型“貓”的容器,別人是可以輕易將“狗”放入容器

  2. 因爲丟失了類型信息,容器只知道它保存的是Object類型的引用。在使用容器中的元素前必須要做類型轉換操作

1.3 迭代器

任何容器都必須實現有方法可以將東西方法放進去,然後有方法將東西取出來。畢竟,存放事物是容器最基本的工作。對於ArrayListadd() 是插入對象的方法,而get() 是取出元素的方法之一。但是如果原本是使用ArrayList,後來考慮到容器的特點,想換用Set 怎麼做?難道重寫代碼嗎?
當然不是,迭代器就是更好的實現這種目的。迭代器是一個對象,它的工作是遍歷並選擇序列中的對象。迭代器通常被稱爲“輕量值”對象:創建它的代價小。因此經常可以見到對迭代器有些奇怪的限制。

如Java的Iterator就是迭代器受限制的例子,它只能用來:
☞ 使用方法iterator() 要求容器返回一個Iterator。第一次調用Iterator的next()方法時,它返回序列中的下一個元素。
☞ 使用next() 獲得序列中的下一個元素。
☞ 使用hasNext() 檢查序列中是否還有元素。
☞ 使用remove() 將上一次返回的元素從迭代器中移除。

///創建一個通用的打印方法
public class Main {   
    static void printAll(Iterator e) { 
      while(e.hasNext())
      Syste.out.println(e.next()); 
       } 
   } 

二、 常見的集合類

在這裏插入圖片描述

2.1 Collection詳解

此圖摘取於:Java集合詳解
在這裏插入圖片描述
Collection接口是List、Set接口和Queue接口的父接口。Collection是集合類(Map除外)的根接口。
Collection提供瞭如下方法對List集合元素進行排序:

1.void reverse(List list): 對指定 List 集合元素進行逆向排序。
2.void shuffle(List list): 對 List 集合元素進行隨機排序(shuffle 方法模擬了“洗牌”動作)。
3.void sort(List list): 根據元素的自然順序對指定 List 集合的元素按升序進行排序。
4.void sort(List list, Comparator c): 根據指定 Comparator 產生的順序對 List 集合元素進行排序。
5.void swap(List list, int i, int j): 將指定 List 集合中的 i 處元素和 j 處元素進行交換
6.void rotate(List list, int distance): 當 distance 爲正數時,將 list 集合的後 distance 個元素“整體”移到前面;當 distance 爲負數時,將 list 集合的前 distance 個元素“整體”移到後面。該方法不會改變集合的長度。

Collection 還提供瞭如下常用的用於查找、替換集合元素的方法:

1.int binarySearch(List list, Object key): 使用二分搜索法搜索指定的 List 集合,以獲得指定對象在 List 集合中的索引。保證 List 中的元素已經處於有序狀態。
2.Object max(Collection coll): 根據元素的自然順序,返回給定集合中的最大元素
3.Object max(Collection coll, Comparator comp): 根據 Comparator 指定的順序,返回給定集合中的最大元素。
4.Object min(Collection coll): 根據元素的自然順序,返回給定集合中的最小元素。
5.Object min(Collection coll, Comparator comp): 根據 Comparator 指定的順序,返回給定集合中的最小元素。
6.void fill(List list, Object obj): 使用指定元素 obj 替換指定 List 集合中的所有元素
7.int frequency(Collection c, Object o): 返回指定集合中指定元素的出現次數
8.int indexOfSubList(List source, List target): 返回子 List 對象在父 List 對象中第一次出現的位置索引;如果父 List 中沒有出現這樣的子 List,則返回 -1。
9.int lastIndexOfSubList(List source, List target): 返回子 List 對象在父 List 對象中最後一次出現的位置索引;如果父 List 中沒有岀現這樣的子 List,則返回 -1。
10.boolean replaceAll(List list, Object oldVal, Object newVal): 使用一個新值 newVal 替換 List 對象的所有舊值 oldVal。

瞭解指定的排序規則:
Java提供了只包含一個compareTo()方法的Comparable接口。包含compare()equals() 兩個方法的Comparator接口。

Comparable和Comparator兩個接口的區別:
Comparable(通過實體對象來調用): 強行對實現它的每個類的對象進行整體排序。這種排序被稱爲類的自然排序,類的compareTo方法被稱爲它的自然比較方法。只能在類中實現compareTo()一次,不能經常修改類的代碼實現自己想要的排序。實現此接口的對象列表(和數組)可以通過Collections.sort(和Arrays.sort)進行自動排序,對象可以用作有序映射中的鍵或有序集合中的元素,無需指定比較器。
Comparator(比較器,可以直接執行): 強行對某個對象進行整體排序。可以將Comparator 傳遞給sort方法(如Collections.sort或Arrays.sort),從而允許在排序順序上實現精確控制。還可以使用Comparator來控制某些數據結構(如有序set或有序映射)的順序,或者爲那些沒有自然順序的對象collection提供排序

2.1.1 List接口

List接口中元素的存放特點是:元素存放有序,同一元素可重複,帶索引的集合。List接口存在三個實現類:ArrayList、LinkedList和Vector

☞ ArrayList類

ArrayList類實現了可變數組的大小,存儲在內的數據稱爲元素,它還提供了快速基於索引訪問元素的方式。元素增刪慢,查找快,ArrayList最常用來查詢數據、遍歷數據。
ArrayList類除了包含Collection接口中的所有方法之外,還包括以下方法:
在這裏插入圖片描述
☞ LinkedList類

LinkedList類採用鏈表結構保存對象,這種結構的有點是便於向集合中插入或者刪除元素。需要頻繁向集合中插入和刪除元素時,使用LinkedList類比ArrayList類效果高,但是Linkedlist類隨機訪問元素的速度則相對較慢。這裏的隨機訪問是指檢索集合中特定索引位置的元素。
LinkedList類 除了包含 Collection 接口和 List 接口中的所有方法之外,還包含以下方法。
在這裏插入圖片描述
☞ Vector類

與ArrayList類似,但屬於強同步類(線程安全)。如果你的程序本身是線程安全的(thread-safe,沒有在多個線程之間共享同一個集合/對象),那麼使用ArrayList是更好的選擇。越安全,效率越低。(所以Java中很少使用Vector類)

☞ ArrayList、LinkedList和Vector之間的區別:

ArrayList和LinkedList:
1.ArrayList是實現了基於動態數組的數據結構,LinkedList基於鏈表的數結構。
2.對於隨機訪問get和set,ArrayList優於LinkedList,由於LinkedList要移動指針
3.對於新增和刪除操作的add和remove,LinkedList優於ArrayList,由於ArrayList要移動數據。(但是如果只對單條數據的插入或刪除,ArrayList優於LinkedList)

ArrayList和Vector的區別:
1.同步性:Vector是線程性同步,所以它是線程安全的,而ArrayList是線程異步的,是不安全。
2.數據增長:從內部實現機制來講,ArrayList和Vector都是使用數組來控制集合的對象,如果集合中的元素的數目大於目前集合數組的長度時,Vector增長率爲目前數組長度的100%,而ArrayList增長率爲,目前數組長度的50%。所以如果在集合中數據量比較大的數據,用Vector有一定的優勢。

2.1.2 Set接口

Set集合類似於一個罐子,程序可以依次把多個對象“丟進”Set集合,而Set集合通常不能記住元素的添加順序。也就是Set集合中的對象不按特定的方式排序,只是簡單地把對象加入集合。Set集合中不能包含重複的對象(如果向Set集合中添加兩個相同的元素,則後添加的會覆蓋前面添加的元素,即在Set集合中不會出現相同的元素),並且最多隻允許包含一個null元素。

Set實現了Collection接口,實際上Set就是Collection,只是行爲不同而已。Set於Collection接口中的方法基本一致,並沒有對Collection接口進行功能上的擴充,只是比Collection接口更加嚴格了。Set接口中元素無序,並且都會以某種規則保證存入的元素不出現重複。它主要有兩個主要的實現類:HashSetTreeSet

☞ HashSet類

HashSet是按照Hash算法來存儲集合中的元素,因此具有很好的存取和查找性能。保證元素的唯一性方式依賴於:hashCodeequals方法。java.util.HashSet底層的實現其實是一個java.util.HashMap支持。

HashSet具有以下特點:
1.不能保證元素的排列順序,順序可能與添加順序不同,順序也有可能發生變化。
2.HashSet不是同步的(線程不安全的),如果多個線程同時訪問或修改一個HashSet,則必須通過代碼來保持同步。
3.集合元素值可以是null。

我們都知道HashSet保證了元素唯一,可是元素存放進去是沒有順序的,那麼我們要保證有序的話:
在這裏插入圖片描述
☞ TreeSet類

TreeSet類同時實現Set接口和SortedSet接口。SortedSet接口是Set接口的子接口,可以實現對集合進行自然排序(升序),因此使用TreeSet類實現的Set接口默認情況下是自然排序的。TreeSet只能實現了Comparable接口的類對象進行排序,因爲Comparable接口中有一個**compareTo(Object o)**方法用於比較兩個對象的大小。因爲Comparable接口中有一個compareTo(Object o)方法用於比較兩個對象的大小。例如a.compareTo(b),如果a==b,則該方法返回0;如果a>b,返回大於0的值;如果a<b,則該方法返回小於0的值。
Tree類除了實現Collection接口的所有方法之外,還實現以下方法:
在這裏插入圖片描述

HashSet類和TreeSet的區別:

實現方式 數據是否有序 是否可以放入null值
HashSet 哈希表實現 HashSet中的數據是無序的 可以放入null,但只能放入一個null
TreeSet 二叉樹實現 TreeSet的數據是自動排好序的 不允許放入null值

2.2 Map詳解

此圖摘取於:Java集合詳解
在這裏插入圖片描述
Map是一種鍵-值對集合,Map集合中的每一個元素都包含一個鍵(key)對象和一個值(value)對象。用於保存具有映射關係的數據。(鍵不允許重複,但允許值重複)
Map中的key和value之間存在的單向一對一關係,即通過指定的key,總能找到唯一的、確定的value。從Map中取出數據時,只要給出指定的key,就可以取出對應的value。
Map接口主要有兩個實現類:HashMap類和TreeMap類。其中,HashMap類按哈希算法來存取鍵對象,而TreeMap類可以對鍵對象進行排序。

☞ HashMap類
HashMap是一個最常用的Map,它根據的HashCode值存儲數據,根據鍵可以直接獲取它的值,具有很快的訪問速度。

HashMap的特點:
1.允許一條記錄鍵爲NULL;允許多條記錄的值爲NULL
2.不支持線程同步

Hashable: 線程安全的,不允許NULL的鍵或值。
LinkedHashMap: 保留數據的存入順序(和LinkedHastSet用法類似)

TreeMap類
TreeMap實現SortMap接口,能夠把它保存的記錄根據鍵排序,默認是按鍵值的升序排序,也可以用指定排序的比較器。
TreeMap 類的使用方法與 HashMap 類相同,唯一不同的是 TreeMap 類可以對鍵對象進行排序:
在這裏插入圖片描述
其他一些方法:isEmpty() 判斷Map是否爲空、size() 返回鍵值對個數、Collection values() 返回Map裏所有value組成的Collection等。
Entry鍵值對對象

我們已經知道,Map中存放的是兩種對象,一種稱爲key(鍵),一種稱爲value(值),它們在在Map中是一一對應關係,這一對對象又稱做Map中的一個Entry(項)。Entry將鍵值對的對應關係封裝成了對象。即鍵值對對象,這樣我們在遍歷Map集合時,就可以從每一個鍵值對(Entry)對象中獲取對應的鍵與對應的值。

既然Entry表示了一對鍵和值,那麼也同樣提供了獲取對應鍵和對應值得方法:
public K getKey(): 獲取Entry對象中的鍵。public V getValue(): 獲取Entry對象中的值。
在Map集合中也提供了獲取所有Entry對象的方法:
**public Set <Map.Entry<K,V>> entrySet()😗*獲取到Map集合中所有的鍵值對對象的集合(Set集合)。

三、參考資料

1.C語言中文網
2.Java集合詳解
3.https://zhidao.baidu.com/question/85559012.html
4.《Java編程思想》
5.《Java核心技術卷Ⅰ》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章