Java集合類初探

目錄

概述

  Java中基本的經常使用的集合類,主要包含:編程

  • List
  • Set
  • Queue
  • Map

這幾種類型的繼承關係如圖: 圖片引自——Collection 和 Map的繼承體系

其中 List、Queue 和 Set 繼承自 Collection 接口,這三種集合的結構都比較簡單,都是普通的元素的集合,而 Map 相對複雜一點,是鍵值對(key-value)的結構。數組

Iterable和Iterator


Iterable

  Iterable 接口是 Collection 接口的「超類」,也就是說 Iterable 接口是 List、Set、Queue 這類簡單集合的頂級接口,看下 Iterable 接口有些啥:

Iterable 接口包含三個方法:app

  • iterator() 返回一個迭代器用於迭代、遍歷集合;
  • forEach(Consumer<? super T>) 加強型for循環,配合 lambda 表達式食用更香;
  • spliterator() 一樣返回一個迭代器,該迭代器是「可分割迭代器」,爲並行遍歷集合而設計。

Iterable 接口的 forEach() 和 spliterator() 方法是用 default 關鍵字修飾的,接口裏包含了方法的默認實現。函數式編程

Iterator

  Iterator 也是一個接口,用於集合的遍歷:
函數

  • hasNext() 是否還有下一個元素,用於控制集合的遍歷的結束;
  • next() 返回一個元素,遊標日後移。
  • remove() 去除當前的元素(最近一次調用 next() 返回的元素)。想要在遍歷集合時刪除元素,須要用到 Iterator 迭代器和該方法。
  • forEachRemaining(Consumer<? super E>) 對剩下的元素(即還沒有被遍歷到的元素)進行某些操做。和 Iterable 接口的 forEach() 有點相似。

Collection


  Collection 接口包含了集合的基本的增刪查操做。既然是集合,那麼如下基本方法是很是必要的:.net

  • 獲取集合大小: size();
  • 添加元素: add();
  • 移除元素: remove();
  • 判斷包含: contains();
  • 判斷元素是否相等: equals();

爲了增長可用性,又加多了幾個方法:設計

  • isEmpty() 判空,少寫幾句 "collection.size==0";3d

  • containsAll() 判斷是否包含另外一個集合裏的全部元素;對象

  • toArray()、toArray(T[]) 把集合轉化爲數組;blog

  • clear() 清除全部元素;

  • removeIf() 條件刪除;

  • stream() 流操做;

  • removeAll() 取補集,把另外一個集合也包含的元素去除;

  • addAll() 把另外一個集合的元素添加進來,至關於取並集;

  • retainAll() 取交集,把另外一個集合也包含的元素保留下來;

  • stream()、parrallelStream() 流操做、並行流操做。

List


  List 中文譯做「清單、列表」,List 是有序的,是按照必定的順序來存儲元素的,既然是有序的集合,就應該能夠經過「遊標」來進行訪問,所以,List 在 Collection 的基礎上添加了經過遊標訪問元素,或經過元素獲取遊標的方法:

  • get(int);

  • add(int, E);

  • remove(int);

  • indexOf(Object);

  • subList(int, int);經過遊標截取子序列。

  • lastIndexOf(Object); 由於 List 是有序的,因此能夠經過「遊標」肯定惟一的元素,所以 List 是容許集合中包含相同(相等)的多個元素的,lastIndexOf(Object) 能夠用來在集合包含多個相同元素時,獲取該元素最後出現的位置。

除此以外,List 還加上了 Collection 沒有的「改」操做,實現了集合的「增刪查改」:

  • set(int, E); 替換某個位置的元素,既然是替換,前提條件是該位置含有元素。

由於 List 是有序集合,所以給 List 加上排序操做是可取的:

  • sort(Comparator<? super E>);

在List接口中有一個 「ListIerator()」的方法,該方法返回一個 ListIterator 對象。

ListIterator 繼承了 Iterator 接口,提供了 previous 操做,以及與遊標相關的 nextIndex() 和 previousIndex()。

Queue


  Queue(隊列)是一種特殊的線性表,有的時候咱們會由於業務需求,須要一個「規定容量的Queue」,這時,若是隊列滿了卻又要添加元素,該採起怎樣的策略,或者隊列爲空時調用remove該如何處理,這是須要考慮的。Queue 繼承了 Collection,又提供了幾個本身的方法:

  • offer(E): 隊尾添加元素,與 add 對應,當隊列已滿時返回false, add()方法這種狀況下則會拋出異常。

  • poll(): 查詢並刪除隊頭元素,與 remove 對應,當隊列爲空時,不會像 remove 那樣拋出異常,而是會返回 null;

  • element(): 查詢隊頭元素但不刪除,與 peek 對應,隊列爲空時拋出異常。

  • peek(): 查詢隊頭元素但不刪除,隊列爲空時返回 null;

Set


  Set 中文是「一組、一套」的意思。與 List 相比,Set 沒有 List 的「列表、清單」的「列」的語義。Set 是無序的。 Set 與 Collection 在語義以及屬性上最爲接近,Set 繼承了 Collection 的方法,沒有本身新添加的方法,以下所示:

  
Set 是沒有 List 的 Index 的概念的,List 能夠用 index 惟一肯定一個元素,Map 能夠用 key 惟一肯定一個元素,而 Set 只能靠自身來惟一肯定一個元素,因此 Set 裏面的元素是不能重複的。正由於 Set 這一特性,可使用 Set 給集合去重。

Map

  在詞典中,Map 做動詞時是「映射」的意思,key-value,key 映射到 value,能夠經過 key 來獲取 value。Map 和 Iterable 同樣是頂級接口。Map 接口 UML 圖以下:

雖然 Map 是一個頂級接口,可是 Map 和 Set、List、Queue應該是同一層級的接口,它們的方法不少是相似的(功能上)。
基本的增刪查改:

  • size();
  • isEmpty();
  • containsKey();
  • containsValue();
  • get();
  • put();
  • remove();
  • putAll();
  • clear();
  • replace()

鍵和值的遍歷:

  • keySet(): 返回 key 的 Set 集合,由於 Map 靠 key 來惟一肯定一個元素,因此 Map 的 key 是不能重複的,天然地,返回的 key 集合是一個 Set;

  • values(): value 的值不會影響到 Map 的結構,value 是能夠重複的,也是能夠爲 null 的,因此返回的 value 集合應該是一個 Collection;

  • entrySet: 該方法返回的是 Entry 的 Set 集合, Entry 是 Map 的內部接口,可把其看做一對鍵值對的組合:

其它的方法:

  • getOrDefault(Object, V): 若是找到 key 爲 object 的鍵值對,則返回其 value, 不然返回本身傳入的 V;

  • putIfAbsent(K, V): 與 put(K, V) 對應,若是 Map 中已經包含 key 爲 K 的鍵值對或鍵值對的值爲空,put(K, V) 方法會用 V 覆蓋原來的值;而 putIfAbsent(K, V)方法僅返回如今的值,不覆蓋;當 Map 中不存在 key 爲 k 的鍵值對時,put 和 putIfAbsent 都會添加新的元素。 概況說就是若是指定的鍵還沒有映射(映射即關聯,就是 key 和 value 的關聯關係, value 爲 null 也視爲未映射或者說未關聯),將其與給定值相關聯並返回 null ,不然返回當前值。

  • compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction): 傳一個BiFunction 對象進去實現值的「計算」,此處的「計算」應該是指「操做」,不只僅是指算術上的「計算」。這與 VueJS 的「計算屬性」有點相似。能夠經過該方法實現 Map 數據的轉換、數據的統計。
    BiFunction是一個接口,關鍵方法和說明以下圖所示,可配合 lambda 表達式,是函數式編程的思想。



    詳情見Java基礎之Java8中Map的compute的使用

  • computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction): 同 putIfAbsent 同樣,若是 key 未映射( value 爲 null 也視爲未映射),則嘗試使用給定的映射函數計算其值,並將其輸入到此映射中(即設置 value )。

  • computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction): Present 與 Absent 相反,前者是「存在」的意思,後者是「不在」的意思,顧名思義,該方法是在指定的 key 在 Map 中存在映射時,則嘗試計算給定key 及其當前值的新值。

  • merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction): merge 其實與 compute 這幾個方法的做用是同樣的,對 key 映射的 value 值進行變換,只是該方法多提供了一個參數 「V value」,至關於用這個參數的 value 和 key 所對應的 value 結合merge)起來一塊兒變換;   好比想要讓 Map 中存儲的學生的年齡加「1」,使用 computer 的話,能夠在函數裏寫定參數「1」;使用 merge 的話,能夠在調用 merge 方法時把「1」傳進去。這時,若是需求變了,年齡不是加「1」,而是加「2」,使用compute 方法的話須要到方法裏面改這個「1」(magic num);而使用 merge 的話只須要在方法調用時改參數,不用改其它代碼。

相關文章
相關標籤/搜索