數組是一種很常見的數據結構,開始接觸編程的時候多數程序都和數組相關。剛開始接觸Java時也是一直使用數組寫一些程序,后來越來越覺得數組這東西沒法滿足需求了,這時一位“前輩”對我說了一句:不會用集合類就等于沒學過Java。然后才知道有集合類。
想想已經是3、4年前的事了,時間如白駒過隙啊。
什么時候數組會顯得力不從心,沒法滿足需求,需要集合類呢?
不知道具體數據長度
需要自動排序
存儲鍵值對
當然,上面的情況不是絕對的,只是數組比較難滿足。這時集合類(也可稱為容器類)就顯示了它強大的功能。
集合類的分類(圖片轉自http://biancheng.dnbcw.info/1000wen/359774.html)
上圖中不包含Queue內容,部分Map的實現類未給出。
常見使用的有List、Set、Map及他們的實現類。
List、Set、Map接口及各實現類的特性
接口
特性
實現類
實現類特性
成員要求
List
線性、有序的存儲容器,可通過索引訪問元素
ArrayList
數組實現。非同步。
Vector
類似ArrayList,同步。
LinkedList
雙向鏈表。非同步。
Map
保存鍵值對成員
HashMap
基于哈希表的?Map?接口的實現,滿足通用需求
任意Object對象,如果修改了equals方法,需同時修改hashCode方法
TreeMap
默認根據自然順序進行排序,或者根據創建映射時提供的?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 ArrayList arrayList = 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 ArrayList arrList = 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");
執行時間比較
執行次數(在0號位置插入)
ArrayList所用時間(ms)
LinkedList所用時間(ms)
10000
31
0
20000
141
0
40000
484
16
80000
1985
0
160000
7906
0
320000
31719
16
執行次數(在尾部插入)
ArrayList所用時間(ms)
LinkedList所用時間(ms)
10000
0
0
20000
15
0
40000
0
0
80000
0
0
160000
0
15
320000
0
16
循環輸出次數(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循環或Iterator遍歷LinkedList效率將提高很多)。
Map
Map基本操作
1 HashMap map = 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
1 List list = new ArrayList();2 list.add(3);3 list.add(4);4 HashSet hashSet = new HashSet();5 hashSet.add(1);6 hashSet.add(3);7 hashSet.add(2);8 hashSet.add(6);9 //重復元素將不能被添加
10 hashSet.add(3);11 //只要有元素被添加就返回true
12 if(hashSet.addAll(list)) {13 System.out.println("Add success");14 }15 //判斷是否存在某個集合
16 if(hashSet.containsAll(list)) {17 System.out.println("The hashSet is contain 3 and 4");18 }19 Iterator it =hashSet.iterator();20 while(it.hasNext()) {21 System.out.print(it.next() + " ");22 //1 2 3 4 623 //看結果是被排序了,HashSet按照Hash函數排序,Integer值的HashCode就是其int值
24 }25 //換轉成數組
26 Object[] integers =hashSet.toArray();27 for (int i = 0; i < integers.length; i++) {28 System.out.print((Integer) integers[i]);29 }30 //移除元素
31 hashSet.remove(3);32
33 TreeSet treeSet = new TreeSet();34 treeSet.add("C");35 treeSet.add("A");36 treeSet.add("D");37 treeSet.add("B");38 for (Iterator strIt =treeSet.iterator(); strIt.hasNext();) {39 System.out.print(strIt.next());40 //ABCD 按照字母順序
41 }42 LinkedHashSet linkedHashSet = new LinkedHashSet();43 linkedHashSet.add("C");44 linkedHashSet.add("A");45 linkedHashSet.add("D");46 linkedHashSet.add("B");47 for (Iterator linkedIt =linkedHashSet.iterator(); linkedIt48 .hasNext();) {49 System.out.print(linkedIt.next());50 //CADB 按照插入順序
51 }
本文沒有對ArrayList及HashMap進行深入的分析,這兩個類是集合類中最常用的類,將另開文章進行深入剖析。