1. 程式人生 > >Android-Java:常用基本容器學習總結

Android-Java:常用基本容器學習總結

Android-Java:常用基本容器學習總結

1.常用容器的總體框架

在這裡插入圖片描述

2.常用容器類的重點

1. ArrayList

https://www.cnblogs.com/skywang12345/p/3308556.html

1.1 儲存結構:

在這裡插入圖片描述
value值存在elementData這個Object型別的陣列中,預設容量是10。

1.2 容器特點:

  1. ArrayList 是一個數組佇列,相當於 動態陣列。與Java中的陣列相比,它的容量能動態增長。
  2. ArrayList 實現java.io.Serializable介面,這意味著ArrayList支援序列化,能通過序列化去傳輸.
  3. ArrayList中的操作不是執行緒安全的!所以,建議在單執行緒中才使用ArrayList.

1.3 注意事項:

  1. 遍歷ArrayList時,使用隨機訪問(即,通過索引序號訪問)效率最高,而使用迭代器的效率最低
  2. ArrayList中的操作不是執行緒安全的!所以,建議在單執行緒中才使用ArrayList.

2. Vector

Vector 是向量佇列,繼承於AbstractList,實現了List, RandomAccess, Cloneable這些介面。
https://www.cnblogs.com/skywang12345/p/3308833.html

2.1 儲存結構:

在這裡插入圖片描述
value值存在elementData這個Object型別的陣列中,預設容量是10。

2.2 容器特點:

  1. Vector中的操作是執行緒安全的,add(),remove(),clear()等操作均加上了synchronized保護;
    在這裡插入圖片描述

3. Stack

Stack是繼承Vector來實現,基於Vector的addElement和removeElement來實現push,pop,peek操作,因此Stack也是通過陣列實現的,而非連結串列。

3.1 儲存結構:

實質上還是用的Vector的陣列實現:
在這裡插入圖片描述

3.2 容器特點:

  1. Stack實際上也是通過陣列去實現的。
    執行push時(即,將元素推入棧中),是通過將元素追加的陣列的末尾中。
    執行peek時(即,取出棧頂元素,不執行刪除),是返回陣列末尾的元素。
    執行pop時(即,取出棧頂元素,並將該元素從棧中刪除),是取出陣列末尾的元素,然後將該元素從陣列中刪除。
  2. Stack繼承於Vector,意味著Vector擁有的屬性和功能,Stack都擁有。

4. HashMap

http://androidxref.com/9.0.0_r3/xref/libcore/ojluni/src/main/java/java/util/HashMap.java

4.1 儲存結構:

JDK1.8 連結串列結構優化為陣列+紅黑樹形式:
在這裡插入圖片描述
Node的結構:
JDK1.8 之前資料+連結串列實現:
在這裡插入圖片描述
陣列是HashMap的主體,連結串列,紅黑樹則是主要為了解決雜湊衝突而存在的,如果定位到的陣列位置不含連結串列或紅黑樹,那麼對於查詢,新增等操作很快,僅需一次定址即可;

如果定位到的陣列包含連結串列,對於新增操作,其時間複雜度為O(n),首先遍歷連結串列,存在即覆蓋,否則新增;對於查詢操作來講,仍需遍歷連結串列,然後通過key物件的equals方法逐一比對查詢。

所以,效能考慮,HashMap中的連結串列出現越少,效能才會越好。

4.2 容器特點:

  1. HashMap執行緒不安全;
  2. HashMap可以接受為null的鍵值(key)和值(value)

5. HashTable

HashTable和Hashmap類似,有個HashTableEntry 型別的陣列成員變數table,管理著鍵值對。
在這裡插入圖片描述
Hashtable是synchronized,這意味著Hashtable是執行緒安全的

但是HashTable已經被淘汰了,如果不需要執行緒安全,那麼使用HashMap,如果需要執行緒安全,那麼使用ConcurrentHashMap。

5.1 HashTable方法API:

在這裡插入圖片描述

5.2 容器特點:

  1. Hashtable 的函式都是同步的,這意味著它是執行緒安全的。
  2. 它的key、value都不可以為null。
  3. Hashtable中的對映不是有序的。
  4. 該型別已經提示被淘汰,需要執行緒安全的話可以使用ConcurrentHashMap

6. HashSet

  1. HashSet是一個集合,集合中不允許出現重複元素。
  2. HashSet是基於HashMap實現,HashSet中有一個HashMap的成員變數map,HashSet的Value 值會被以鍵值對<Value,PRESENT>加入到map中,由於HashMap不可以有重複的key,因而實現了set的去重。

6.1 注意事項:

  1. HashSet實現了Set介面,它不允許集合中出現重複元素。當我們提到HashSet時,第一件事就是在將物件儲存在HashSet之前,要確保重寫hashCode()方法和equals()方法,這樣才能比較物件的值是否相等,確保集合中沒有儲存相同的物件。
    案例:https://www.cnblogs.com/dongying/p/4024519.html

7. ConcurrentHashMap

原理:http://www.cnblogs.com/chengxiao/p/6842045.html

7.1 儲存結構:

在這裡插入圖片描述
Segmemt:
每個綠色方塊是ConcurrentHashMap的一個Node:
在這裡插入圖片描述

7.2 容器特點:

1.ConcurrentHashMap是執行緒安全的;
1.ConcurrentHashMap不同於HashMap,它既不允許key值為null,也不允許value值為null;
2.HashTable容器的get方法是需要加鎖的,而ConcurrentHashMap的get操作是不加鎖的,原因是它的get方法裡將要使用的共享變數都定義成volatile;
3.在ConcurrentHashMap中,每個hash區間使用的鎖是ReentrantLock;

Android中獨有的:

8. SparseArray

8.1 儲存結構:

在這裡插入圖片描述

8.2 容器特點

  1. SparseArray在儲存和讀取資料時候,使用的是二分查詢法;
  2. 滿足下面兩個條件我們能夠使用SparseArray取代HashMap:
    a.資料量不大,最好在千級以內;
    b.key必須為int型別,這中情況下的HashMap能夠用SparseArray取代;
  3. SparseArray被稱為稀疏陣列,原因是陣列中可能並不是連續儲存著value,remove方法並沒有去直接刪掉元素,而是將這個key指向了DELETED,這時候value失去了引用,如果沒有其它的引用,會在下一次系統記憶體回收的時候被幹掉,或者該key被複用指向新的值,是一個優化;
  4. SparseArray不需要開闢記憶體空間來額外儲存外部對映,從而節省記憶體,key為int的時候才能使用,注意是int而不是Integer,這也是sparseArray效率提升的一個點,去掉了Hashmap的裝箱的操作。

9. ArrayMap

https://www.jianshu.com/p/1fb660978b14

9.1資料結構:

在這裡插入圖片描述

  1. 資料變數含義:
    (1)mHashes,用於儲存key對應的hashCode;
    (2)mArray,用於儲存鍵值對(key,value),其結構為[key1,value1,key2,value2,key3,value3,…];
    (3)mBaseCache,快取,如果ArrayMap的資料量從4,增加到8,用該陣列儲存之前使用的mHashes和mArray,這樣如果資料量再變回4的時候,可以再次使用之前的陣列,不需要再次申請空間,這樣節省了一定的時間;
    (4)mTwiceBaseCache,與mBaseCache對應,不過觸發的條件是資料量從8增長到12;
  2. allocArrays()
  3. 適用場景:
    a. 資料量不大
    b.空間比時間重要
    c.需要使用Map在Android平臺,相對來說,記憶體容量更寶貴。而且資料量不大。所以當需要使用key是Object型別的Map時,可以考慮使用ArrayMap來替換HashMap
  4. 中佔據時間複雜度最多的屬於第一步:確定key的hashCode在mHahses中的索引值。而這一步對mHashes查詢使用的是二分查詢,即Binary Search。所以ArrayMap的查詢時間複雜度為 ‎O(log n);