數組是一種很常見的數據結構,開始接觸編程的時候多數程序都和數組相關。剛開始接觸Java時也是一直使用數組寫一些程序,后來越來越覺得數組這東西沒法滿足需求了,這時一位“前輩”對我說了一句:不會用集合類就等于沒學過Java。然后才知道有集合類。
java集合類分為:set、list、map、queue四大體系。其中set代表無序、不可重復的集合;list代表有序、可重復的集合。map代表具有映射關系的集合;queue代表隊列集合。
Java集合類與數組的區(qū)別:Java的集合類的長度是動態(tài)的,數組則是固定長度的。
Java集合類與數組的聯系:使用相應的toArray()和Arrays.asList()方法可以回想轉換。
想想已經是3、4年前的事了,時間如白駒過隙啊。
什么時候數組會顯得力不從心,沒法滿足需求,需要集合類呢?
1、不知道具體數據長度
2、需要自動排序
3、存儲鍵值對
當然,上面的情況不是絕對的,只是數組比較難滿足。這時集合類(也可稱為容器類)就顯示了它強大的功能。
集合類的分類
上圖中不包含Queue內容,部分Map的實現類未給出。
常見使用的有List、Set、Map及他們的實現類。
List、Set、Map接口及各實現類的特性
接口 | 特性 | 實現類 | 實現類特性 | 成員要求 |
List | 線性、有序的存儲容器,可通過索引訪問元素 | ArrayList | 數組實現。非同步。 | |
Vector | 類似ArrayList,同步。 | |||
LinkedList | 雙向鏈表。非同步。 | |||
Map | 保存鍵值對成員 | HashMap | 基于哈希表的 Map 接口的實現,滿足通用需求 | 任意Object對象,如果修改了equals方法,需同時修改hashCode方法 |
TreeMap | 默認根據自然順序進行排序,或者根據創(chuàng)建映射時提供的 Comparator進行排序 | 鍵成員要求實現caparable接口,或者使用Comparator構造TreeMap。鍵成員一般為同一類型。 | ||
LinkedHashMap | 類似于HashMap,但迭代遍歷時取得“鍵值對”的順序是其插入順序或者最近最少使用的次序 | 與HashMap相同 | ||
IdentityHashMap | 使用==取代equals()對“鍵值”進行比較的散列映射 | 成員通過==判斷是否相等 | ||
WeakHashMap | 弱鍵映射,允許釋放映射所指向的對象 | |||
ConcurrentHashMap | 線性安全的Map | |||
Set | 成員不能重復 | HashSet | 為快速查找設計的Set | 元素必須定義hashCode() |
TreeSet | 保持次序的Set,底層為樹結構 | 元素必須實現Comparable接口 | ||
LinkedHashSet | 內部使用鏈表維護元素的順序(插入的次序) | 元素必須定義hashCode() |
在滿足要求的情況下,Map應盡量使用HashMap,Set應盡量使用HashSet。
集合類的基本使用
List
List基本操作
1 ArrayListarrayList = new ArrayList (); 2 arrayList.add("Tom"); 3 arrayList.add("Jerry"); 4 arrayList.add("Micky"); 5 // 使用Iterator遍歷元素 6 Iterator it = arrayList.iterator(); 7 while (it.hasNext()) { 8 String str = it.next(); 9 System.out.println(str); 10 } 11 // 在指定位置插入元素 12 arrayList.add(2, "Kate"); 13 // 通過索引直接訪問元素 14 for (int i = 0; i < arrayList.size(); i++) { 15 System.out.println(arrayList.get(i)); 16 } 17 List subList = new ArrayList (); 18 subList.add("Mike"); 19 // addAll(Collection<? extends String> c)添加所給集合中的所有元素 20 arrayList.addAll(subList); 21 // 判斷是否包含某個元素 22 if (arrayList.contains("Mike")) { 23 System.out.println("Mike is include in the list"); 24 } 25 26 LinkedList linkedList = new LinkedList (); 27 linkedList.addAll(arrayList); 28 // 獲取指定元素 29 System.out.println(linkedList.get(4)); 30 // 獲取第一個元素 31 System.out.println(linkedList.getFirst()); 32 // 獲取最后一個元素 33 System.out.println(linkedList.getLast()); 34 // 獲取并刪除第一個元素 35 System.out.println(linkedList.pollFirst()); 36 // 獲取,但不移除第一個元素 37 System.out.println(linkedList.peekFirst());
ArrayList和LinkedList的效率比較
ArrayList添加元素的效率
1 ArrayListarrList = new ArrayList (); 2 long startTimeMillis, endTimeMillis; 3 startTimeMillis = System.currentTimeMillis(); 4 for (int i = 0; i < 10000; i++) { 5 arrList.add(0, "addString"); 6 } 7 endTimeMillis = System.currentTimeMillis(); 8 System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis) 9 + "ms"); 10 11 arrList.clear(); 12 13 startTimeMillis = System.currentTimeMillis(); 14 for (int i = 0; i < 20000; i++) { 15 arrList.add(0, "addString"); 16 } 17 endTimeMillis = System.currentTimeMillis(); 18 System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis) 19 + "ms"); 20 21 arrList.clear(); 22 23 startTimeMillis = System.currentTimeMillis(); 24 for (int i = 0; i < 40000; i++) { 25 arrList.add(0, "addString"); 26 } 27 endTimeMillis = System.currentTimeMillis(); 28 System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis) 29 + "ms"); 30 31 arrList.clear(); 32 33 startTimeMillis = System.currentTimeMillis(); 34 for (int i = 0; i < 80000; i++) { 35 arrList.add(0, "addString"); 36 } 37 endTimeMillis = System.currentTimeMillis(); 38 System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis) 39 + "ms"); 40 41 arrList.clear(); 42 43 startTimeMillis = System.currentTimeMillis(); 44 for (int i = 0; i < 160000; i++) { 45 arrList.add(0, "addString"); 46 } 47 endTimeMillis = System.currentTimeMillis(); 48 System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis) 49 + "ms"); 50 51 arrList.clear(); 52 53 startTimeMillis = System.currentTimeMillis(); 54 for (int i = 0; i < 320000; i++) { 55 arrList.add(0, "addString"); 56 } 57 endTimeMillis = System.currentTimeMillis(); 58 System.out.println("ArrayList:" + (endTimeMillis - startTimeMillis) 59 + "ms");
執(zhí)行時間比較
執(zhí)行次數(在0號位置插入) | ArrayList所用時間(ms) | LinkedList所用時間(ms) |
10000 | 31 | 0 |
20000 | 141 | 0 |
40000 | 484 | 16 |
80000 | 1985 | 0 |
160000 | 7906 | 0 |
320000 | 31719 | 16 |
執(zhí)行次數(在尾部插入) | ArrayList所用時間(ms) | LinkedList所用時間(ms) |
10000 | 0 | 0 |
20000 | 15 | 0 |
40000 | 0 | 0 |
80000 | 0 | 0 |
160000 | 0 | 15 |
320000 | 0 | 16 |
循環(huán)輸出次數(get(index)方法) | ArrayList所用時間(ms) | LinkedList所用時間(ms) |
10000 | 93 | 204 |
20000 | 188 | 797 |
40000 | 328 | 2734 |
80000 | 688 | 13328 |
160000 | 1594 | 62313 |
320000 | 2765 | 太久了…… |
因為ArrayList底層由數組實現,在0號位置插入時將移動list的所有元素,在末尾插入元素時不需要移動。LinkedList是雙向鏈表,在任意位置插入元素所需時間均相同。所以在List中有較多插入和刪除操作的情況下應使用LinkedList來提高效率,而有較多索引查詢的時候使用ArrayList(使用增強型的for循環(huán)或Iterator遍歷LinkedList效率將提高很多)。
Map
Map基本操作
1 HashMapmap = new HashMap (); 2 // 向Map中添加元素 3 map.put("Tom", 26); 4 map.put("Jack", 18); 5 map.put("Micky", 17); 6 map.put("Kate", 15); 7 // 根據Key獲取Value 8 System.out.println("Jack is " + map.get("Jack") + " years old"); 9 // 移除 10 map.remove("Micky"); 11 // 遍歷Map 12 for (Entry entry : map.entrySet()) { 13 System.out.println("name:" + entry.getKey() + " age:" 14 + entry.getValue()); 15 } 16 // Key相同的元素將被覆蓋 17 map.put("Jack", 19); 18 // 根據Key獲取Value 19 System.out.println("Jack is " + map.get("Jack") + " years old"); 20 // 判斷是否包含某個Key 21 if (map.containsKey("Tom")) { 22 System.out.println(map.get("Tom")); 23 } 24 // 判斷是否包含某個Value 25 if (map.containsValue(26)) { 26 System.out.println("The map include the value 26"); 27 } 28 // 判斷map是否為空 29 if (!map.isEmpty()) { 30 // 獲取map大小 31 System.out.println("The map's size=" + map.size()); 32 } 33 // 獲取Key的集合 34 for (String str : map.keySet()) { 35 System.out.println(str); 36 } 37 38 TreeMap treeMap = new TreeMap (); 39 treeMap.putAll(map); 40 // 輸出內容按照key值排序 41 for (Entry entry : treeMap.entrySet()) { 42 System.out.println("name:" + entry.getKey() + " age:" 43 + entry.getValue()); 44 // name:Jack age:19 45 // name:Kate age:15 46 // name:Tom age:26 47 } 48 49 LinkedHashMap linkedHashMap = new LinkedHashMap (); 50 // 向Map中添加元素 51 linkedHashMap.put("Tom", 26); 52 linkedHashMap.put("Jack", 18); 53 linkedHashMap.put("Micky", 17); 54 linkedHashMap.put("Kate", 15); 55 // 保持了插入的順序 56 for (Entry entry : linkedHashMap.entrySet()) { 57 System.out.println("name:" + entry.getKey() + " age:" 58 + entry.getValue()); 59 // name:Tom age:26 60 // name:Jack age:18 61 // name:Micky age:17 62 // name:Kate age:15 63 }
Set
Set基本操作
1 HashMapmap = new HashMap (); 2 // 向Map中添加元素 3 map.put("Tom", 26); 4 map.put("Jack", 18); 5 map.put("Micky", 17); 6 map.put("Kate", 15); 7 // 根據Key獲取Value 8 System.out.println("Jack is " + map.get("Jack") + " years old"); 9 // 移除 10 map.remove("Micky"); 11 // 遍歷Map 12 for (Entry entry : map.entrySet()) { 13 System.out.println("name:" + entry.getKey() + " age:" 14 + entry.getValue()); 15 } 16 // Key相同的元素將被覆蓋 17 map.put("Jack", 19); 18 // 根據Key獲取Value 19 System.out.println("Jack is " + map.get("Jack") + " years old"); 20 // 判斷是否包含某個Key 21 if (map.containsKey("Tom")) { 22 System.out.println(map.get("Tom")); 23 } 24 // 判斷是否包含某個Value 25 if (map.containsValue(26)) { 26 System.out.println("The map include the value 26"); 27 } 28 // 判斷map是否為空 29 if (!map.isEmpty()) { 30 // 獲取map大小 31 System.out.println("The map's size=" + map.size()); 32 } 33 // 獲取Key的集合 34 for (String str : map.keySet()) { 35 System.out.println(str); 36 } 37 38 TreeMap treeMap = new TreeMap (); 39 treeMap.putAll(map); 40 // 輸出內容按照key值排序 41 for (Entry entry : treeMap.entrySet()) { 42 System.out.println("name:" + entry.getKey() + " age:" 43 + entry.getValue()); 44 // name:Jack age:19 45 // name:Kate age:15 46 // name:Tom age:26 47 } 48 49 LinkedHashMap linkedHashMap = new LinkedHashMap (); 50 // 向Map中添加元素 51 linkedHashMap.put("Tom", 26); 52 linkedHashMap.put("Jack", 18); 53 linkedHashMap.put("Micky", 17); 54 linkedHashMap.put("Kate", 15); 55 // 保持了插入的順序 56 for (Entry entry : linkedHashMap.entrySet()) { 57 System.out.println("name:" + entry.getKey() + " age:" 58 + entry.getValue()); 59 // name:Tom age:26 60 // name:Jack age:18 61 // name:Micky age:17 62 // name:Kate age:15 63 }
本文沒有對ArrayList及HashMap進行深入的分析,這兩個類是集合類中最常用的類,將另開文章進行深入剖析。