Android List、Set和Map的介紹和使用
一、前言
Android中常用的資料結構包括List、Set和Map這三大類的集合,其中List和Set屬於Collection。List與Set的區別在於List可以存放重複的資料,但是Set不可以。
Map一般為key-value這樣的對於關係,比如常用的HashMap。
Android中的集合類關係圖
Collection 介面的介面 物件的集合
|-List 子介面 按進入的先後順序進行儲存,可重複
| |-LinkedList 介面實現類 連結串列,插入刪除,非執行緒安全
| |-ArrayList 介面實現類 陣列,隨機訪問,執行緒非安全
| |_Vector 介面實現類 陣列,執行緒安全
|_Set 子介面 僅接收一次,並做內部排序
| |-HashSet 介面實現類 HashSet使用Hash演算法來儲存集合中的元素,因此具有良好的存取和查詢效能
|
| |-LinkedHashSet 介面實現類 LinkedHashSet集合也是根據元素的hashCode值來決定元素的儲存位置,但是和HashSet不同的是,它同時使用連結串列維護元素的次序,這樣使得元素看起來是以插入的順序儲存的。
|—Queue 子介面 保持一個佇列(先進先出)的順序
|-PriorityQueue
Map 介面 把鍵物件和值物件進行關聯的容器,並且值物件可以是另一個Map
|-HashMap 介面實現類 根據key算出一個hash值,確定一個存放index,期間需要解決hash衝突。非執行緒安全。
|-LinkedHashMap 繼承自HashMap 相比HashMap,其特點是內部存放資料是有順序的,增加了記住元素插入或者訪問順序的功能。
|-TreeMap 介面的實現類 使用大致與HashMap類似,只是內部實現是根據紅黑樹來實現的。
|HashTable 介面實現類 Hashtable是執行緒安全的,內部實現與HashMap差不多。
二、List、Set和Map的介紹和使用範例
常用的List包括ArrayList、Linked List和Vector,下面將對他們進行一一介紹。
2.1 ArrayList
ArrayList非執行緒安全,底層由陣列實現,它的構造主要從AbstractList實現,主要是判斷下初始元素的容量,ArrayList最大的特點就是提供了Add、Get操作,當然可以通過迭代器來遍歷,對於元素的存在可以通過contains方法判斷。
ArrayList初始化和賦值
//方式一:
ArrayList<String> list = new ArrayList<String>();
String str01 = String("test1");
String str02 = String("test2");
list.add(test1);
list.add(test2);
//方式二:
ArrayList<String> list = new ArrayList<String>(){{add("test1"); add("test2");}};
ArrayList在使用過程中需要注意的一個問題便是在遍歷的過程中刪除Item元素,該問題的關鍵在於面試者使用的是ArrayList的remove還是Iterator的remove,如果操作不當,會出現刪除的元素並沒有完全被刪除,或者出現ConcurrentModificationException異常。
//採用For迴圈進行刪除,該方法會造成某些物件沒有被刪除的情況
public class Test1 {
public static void main(String[] args) {
ArrayList<String> aList = new ArrayList<String>();
aList.add("a");
aList.add("ab");
aList.add("abc");
aList.add("abc");
aList.add("abcr");
aList.add("abc");
aList.add("abcf");
aList.add("abc");
aList.add("abdc");
for(int i = 0;i < aList.size();i++){
if(aList.get(i).equals("abc")){
aList.remove(i);
}
}
System.out.println(aList);
}
}
//輸出結果為:[a, ab, abc, abcr, abcf, abdc],其中有一個abc沒有被刪除
//採用遍歷器進行刪除
Iterator<String> iter = aList.iterator();
while(iter.hasNext()){
if(iter.next().equals("abc")){
iter.remove();
}
//輸出結果[a, ab, abcr, abcf, abdc]
//採用遍歷器進行刪除
for (String tar : aList) {
if (tar.equals("abc")){
aList.remove(tar);
}
}
//結果是出現異常
綜上所述,在對ArrayList進行遍歷刪除時,建議使用遍歷器iterator進行遍歷刪除。
2.2 LinkedList
Android中的LinkedList是通過雙向列表實現的。連結串列元素除了含有自身的值以外,還含有上一個元素和下一個元素的引用。
private static final class Link<T> {
T data;//當前值
Link<T> previous, next;//上一個,和下個連結串列物件的引用
Link(T o, Link<T> p, Link<T> n) {
data = o;
previous = p;
next = n;
}
}
LinkedList的插入和刪除操作就是雙向連結串列的插入和刪除操作,參加如下:
//插入操作操作
private boolean addLastImpl(E object) {
Link<E> oldLast = voidLink.previous;
//新元素的頭指向上一個元素,尾指向連結串列的頭部
Link<E> newLink = new Link<E>(object, oldLast, voidLink);
//頭元素的頭指向新元素
voidLink.previous = newLink;
//上一個結尾元素的尾 指向新元素
oldLast.next = newLink;
size++;
modCount++;
return true;
}
//刪除操作
@Override
public E remove(int location) {
if (location >= 0 && location < size) {
Link<E> link = voidLink;
if (location < (size / 2)) {
for (int i = 0; i <= location; i++) {
link = link.next;
}
} else {
for (int i = size; i > location; i--) {
link = link.previous;
}
}
Link<E> previous = link.previous;
Link<E> next = link.next;
previous.next = next;
next.previous = previous;
size--;
modCount++;
return link.data;
}
throw new IndexOutOfBoundsException();
}
LinkedList在實現List的介面的同時也實現了Queue的介面。
2.3 Vector
Vector相當於具有同步操作的ArrayList,但是由於同步特性會造成一部分效能的損失。Vector基於陣列和同步特性,支援包括新增、移除和替換元素在內的所有操作,允許包括NULL在內元素。
2.4 HashSet
Set是最簡單的一種集合。集合中的物件不按特定的方式排序,並且沒有重複物件。HashSet類按照雜湊演算法來存取集合中的物件,存取速度比較快。一般會用HashSet對List中相同的元素進行去重,參考如下:
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("f");
list.add("b");
list.add("c");
list.add("a");
list.add("d");
System.out.println(list);
list = removeSame(list);
System.out.println(list);
}
private static List<String> removeSame(List<String> list) {
Set<String> set = new HashSet<>();
set.addAll(list);
List<String> listSingle = new ArrayList<>();
for(String s : set){
listSingle.add(s);
}
return listSingle;
}
2.5 TreeSet和LinkedHashSet
TreeSet儲存次序的Set,底層為樹結構。使用它可以從Set中提取有序的序列。
LinkedHashSet,具有HashSet的查詢速度,且內部使用連結串列維護元素的順序(插入的次序)。於是在使用迭代器遍歷Set時,結構會按元素插入的次序顯示。
2.6 Queue
Queue用於模擬“佇列”這種資料結構(先進先出)。Queue提供的操作函式如下:
入隊 | 出隊 | 檢索 |
---|---|---|
offer(E e) | poll() | peek() |
add(E e) | remove() | element() |
Queue的實現類主要分為三類
非執行緒安全:LinkedList,PriorityQueue等。
執行緒安全:非阻塞ConcurrentLinkedQueue
執行緒安全,阻塞:BlockingQueue實現類:ArrayBlockingQueue,LinkedBlockingQueue,PriorityBlockingQueue。
Queue在Android開發中很多場景都會用到,比如線上程池的任務佇列就一般會用LinkedBlockingQueue來進行存放。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(
nThreads, nThreads,
0L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>() //任務佇列採用LinkedBlockingQueue進行存放
);
2.7 Map
Map除去平常程式碼中用到的儲存鍵值對的功能外,在此只總結一下Map在平常使用中的遍歷操作,參見如下:
// Map.values()遍歷所有的value,不遍歷key
for (String v : map.values()) {
System.out.println("value= " + v);
}
//取二次值,先取key再取value,建議只需要用key的時候使用,節省時間、空間
// keySet遍歷key和value
for (String key : map.keySet()) {
System.out.println("key= "+ key + " and value= " + map.get(key));
}
// 取一次值,一次把key和value全部取出
// entrySet使用iterator遍歷key和value
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
// 推薦,尤其是容量大時,TreeMap尤其推薦
// entrySet遍歷key和value
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
三、Android中常用類其它資料結構
SparseArray型別,SparseArray有如下特性:
1、SparseArray是android提供的一個工具類,它可以用來替代hashmap進行物件的儲存
2、SparseArray比HashMap更省記憶體,它對資料採取了矩陣壓縮的方式來表示稀疏陣列的資料,從而節約記憶體空間
3、SparseArray只能儲存key為整型的資料
4、SparseArray在儲存和讀取資料時候,使用的是二分查詢法,提高了查詢的效率
5、SparseArray有自己的垃圾回收機制。(當數量不是很多的時候,這個不必關心。)
SparseArray的插取
SparseArray<String> sparseArray = new android.util.SparseArray<String>(16);
sparseArray.put(10, "value");
sparseArray.get(10);
四、參考部落格
從原始碼看Android常用的資料結構 ( SDK23版本 ) ( 三 , Queue篇)
Android List,Set,Map集合安全 集合區別 併發集合類效能分析
Android中List、Set、Map資料結構詳解
List、Set、Map 和 Queue 之間的區別
Android之collection(集合)
java 利用HashSet去重並保持排序
Android中的HashMap,ArrayMap和SparseArray
- json = json.replace("\\&", "&");
- json = json.replace(" ", " ");
- json = "[" + json + "]";
- //使用阿里的fastjson進行解析
- List<KuWoInfo> list = JSON.parseArray(json,KuWoInfo.class);
- Log.d(TAG,"--------------->"+list.get(0).getAbslist()[0].getSONGNAME());