Android-Java:常用基本容器學習總結
Android-Java:常用基本容器學習總結
1.常用容器的總體框架
2.常用容器類的重點
1. ArrayList
https://www.cnblogs.com/skywang12345/p/3308556.html
1.1 儲存結構:
value值存在elementData這個Object型別的陣列中,預設容量是10。
1.2 容器特點:
- ArrayList 是一個數組佇列,相當於 動態陣列。與Java中的陣列相比,它的容量能動態增長。
- ArrayList 實現java.io.Serializable介面,這意味著ArrayList支援序列化,能通過序列化去傳輸.
- ArrayList中的操作不是執行緒安全的!所以,建議在單執行緒中才使用ArrayList.
1.3 注意事項:
- 遍歷ArrayList時,使用隨機訪問(即,通過索引序號訪問)效率最高,而使用迭代器的效率最低
- 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 容器特點:
- Vector中的操作是執行緒安全的,add(),remove(),clear()等操作均加上了synchronized保護;
3. Stack
Stack是繼承Vector來實現,基於Vector的addElement和removeElement來實現push,pop,peek操作,因此Stack也是通過陣列實現的,而非連結串列。
3.1 儲存結構:
實質上還是用的Vector的陣列實現:
3.2 容器特點:
- Stack實際上也是通過陣列去實現的。
執行push時(即,將元素推入棧中),是通過將元素追加的陣列的末尾中。
執行peek時(即,取出棧頂元素,不執行刪除),是返回陣列末尾的元素。
執行pop時(即,取出棧頂元素,並將該元素從棧中刪除),是取出陣列末尾的元素,然後將該元素從陣列中刪除。 - 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 容器特點:
- HashMap執行緒不安全;
- HashMap可以接受為null的鍵值(key)和值(value)
5. HashTable
HashTable和Hashmap類似,有個HashTableEntry 型別的陣列成員變數table,管理著鍵值對。
Hashtable是synchronized,這意味著Hashtable是執行緒安全的
但是HashTable已經被淘汰了,如果不需要執行緒安全,那麼使用HashMap,如果需要執行緒安全,那麼使用ConcurrentHashMap。
5.1 HashTable方法API:
5.2 容器特點:
- Hashtable 的函式都是同步的,這意味著它是執行緒安全的。
- 它的key、value都不可以為null。
- Hashtable中的對映不是有序的。
- 該型別已經提示被淘汰,需要執行緒安全的話可以使用ConcurrentHashMap
6. HashSet
- HashSet是一個集合,集合中不允許出現重複元素。
- HashSet是基於HashMap實現,HashSet中有一個HashMap的成員變數map,HashSet的Value 值會被以鍵值對<Value,PRESENT>加入到map中,由於HashMap不可以有重複的key,因而實現了set的去重。
6.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 容器特點
- SparseArray在儲存和讀取資料時候,使用的是二分查詢法;
- 滿足下面兩個條件我們能夠使用SparseArray取代HashMap:
a.資料量不大,最好在千級以內;
b.key必須為int型別,這中情況下的HashMap能夠用SparseArray取代; - SparseArray被稱為稀疏陣列,原因是陣列中可能並不是連續儲存著value,remove方法並沒有去直接刪掉元素,而是將這個key指向了DELETED,這時候value失去了引用,如果沒有其它的引用,會在下一次系統記憶體回收的時候被幹掉,或者該key被複用指向新的值,是一個優化;
- SparseArray不需要開闢記憶體空間來額外儲存外部對映,從而節省記憶體,key為int的時候才能使用,注意是int而不是Integer,這也是sparseArray效率提升的一個點,去掉了Hashmap的裝箱的操作。
9. ArrayMap
https://www.jianshu.com/p/1fb660978b14
9.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; - allocArrays()
- 適用場景:
a. 資料量不大
b.空間比時間重要
c.需要使用Map在Android平臺,相對來說,記憶體容量更寶貴。而且資料量不大。所以當需要使用key是Object型別的Map時,可以考慮使用ArrayMap來替換HashMap - 中佔據時間複雜度最多的屬於第一步:確定key的hashCode在mHahses中的索引值。而這一步對mHashes查詢使用的是二分查詢,即Binary Search。所以ArrayMap的查詢時間複雜度為 O(log n);