一、 認識集合
1、Collection接口是集合類的根接口,Java中沒有提供這個接口的直接的實現類。但是卻讓其被繼承產生了兩個接口,就是Set和List。Set中不能包含重複的元素。List是一個有序的集合,可以包含重複的元素,提供了按索引訪問的方式。
2、Map是Java.util包中的另一個接口,它和Collection接口沒有關係,是相互獨立的,但是都屬於集合類的一部分。Map包含了key-value對。Map不能包含重複的key,但是可以包含相同的value。
Collection
├ List
│ ├ LinkedList
│ ├ ArrayList
│ └ Vector
│ └ Stack
├ Queue
└ Set
├ HashSet
├ TreeSet
Map
├ Hashtable
├ HashMap
└ WeakHashMap
二、幾種重要的接口和類簡介
1、List(有序、可重複)
List裏存放的對象是有序的,同時也是可以重複的,List關注的是索引,擁有一系列和索引相關的方法,查詢速度快。因爲往list集合裏插入或刪除數據時,會伴隨着後面數據的移動,所有插入刪除數據速度慢。
2、Set(無序、不能重複)
Set裏存放的對象是無序的,不能重複的,集合中的對象不按特定的方式排序,只是簡單地把對象加入集合中。
3、Map(鍵值對、鍵唯一、值不唯一)
Map集合中存儲的是鍵值對,鍵不能重複,值可以重複。根據鍵得到值,對map集合遍歷時先得到鍵的set集合,對set集合進行遍歷,得到相應的值。
對比如下:
|
|
是否有序 |
是否允許元素重複 |
Collection |
|
|
|
List |
|
是 |
是 |
Set |
AbstractSet |
否 |
否 |
|
HashSet |
|
|
|
TreeSet |
是(用二叉排序樹) |
|
Map |
AbstractMap |
否 |
使用key-value來映射和存儲數據,key必須唯一,value可以重複 |
|
HashMap |
|
|
|
TreeMap |
是(用二叉排序樹) |
|
三、集合的輸出(遍歷)
1、 在類集中提供了以下四種的常見輸出方式:
1)Iterator:迭代輸出,是使用最多的輸出方式。
Iterator,所有的集合類,都實現了Iterator接口,這是一個用於遍歷集合中元素的接口,主要包含以下三種方法:
1.hasNext()是否還有下一個元素。
2.next()返回下一個元素。
3.remove()刪除當前元素
代碼:
Iterator it = arr.iterator();
while(it.hasNext()){ object o =it.next(); ...}
2)ListIterator:是Iterator的子接口,專門用於輸出List中的內容。
3)foreach輸出:JDK1.5之後提供的新功能,可以輸出數組或集合。
foreach的形式: for(int i:arr){...}
4)for循環
for的形式:for(int i=0;i<arr.size();i++){...}
四、Map集合
實現類:HashMap、Hashtable、LinkedHashMap和TreeMap
1、HashMap(元素不能重複,且沒有順序) :HashMap是最常用的Map,它根據鍵的HashCode值存儲數據,根據鍵可以直接獲取它的值,具有很快的訪問速度,遍歷時,取得數據的順序是完全隨機的。因爲鍵對象不可以重複,所以HashMap最多隻允許一條記錄的鍵爲Null,允許多條記錄的值爲Null,是非同步的
2、Hashtable:Hashtable與HashMap類似,是HashMap的線程安全版,它支持線程的同步,即任一時刻只有一個線程能寫Hashtable,因此也導致了Hashtale在寫入時會比較慢,它繼承自Dictionary類,不同的是它不允許記錄的鍵或者值爲null,同時效率較低。
3、ConcurrentHashMap:線程安全,並且鎖分離。ConcurrentHashMap內部使用段(Segment)來表示這些不同的部分,每個段其實就是一個小的hash table,它們有自己的鎖。只要多個修改操作發生在不同的段上,它們就可以併發進行。
4、LinkedHashMap:LinkedHashMap保存了記錄的插入順序,在用Iteraor遍歷LinkedHashMap時,先得到的記錄肯定是先插入的,在遍歷的時候會比HashMap慢,有HashMap的全部特性。
5、TreeMap(有序):TreeMap實現SortMap接口,能夠把它保存的記錄根據鍵排序,默認是按鍵值的升序排序(自然順序),也可以指定排序的比較器,當用Iterator遍歷TreeMap時,得到的記錄是排過序的。不允許key值爲空,非同步的。
五、Map遍歷
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class TestMap {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "a");
map.put(2, "b");
map.put(3, "ab");
map.put(4, "ab");
map.put(4, "ab");// 和上面相同 , 會自己篩選
System.out.println(map.size());
// 第一種:
/*
* Set<Integer> set = map.keySet(); //得到所有key的集合
*
* for (Integer in : set) { String str = map.get(in);
* System.out.println(in + " " + str); }
*/
System.out.println("第一種:通過Map.keySet遍歷key和value:");
for (Integer in : map.keySet()) {
//map.keySet()返回的是所有key的值
String str = map.get(in);//得到每個key多對用value的值
System.out.println(in + " " + str);
}
// 第二種:
System.out.println("第二種:通過Map.entrySet使用iterator遍歷key和value:");
Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Integer, String> entry = it.next();
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
// 第三種:推薦,尤其是容量大時
System.out.println("第三種:通過Map.entrySet遍歷key和value");
for (Map.Entry<Integer, String> entry : map.entrySet()) {
//Map.entry<Integer,String> 映射項(鍵-值對) 有幾個方法:用上面的名字entry
//entry.getKey() ;entry.getValue(); entry.setValue();
//map.entrySet() 返回此映射中包含的映射關係的 Set視圖。
System.out.println("key= " + entry.getKey() + " and value= "
+ entry.getValue());
}
// 第四種:
System.out.println("第四種:通過Map.values()遍歷所有的value,但不能遍歷key");
for (String v : map.values()) {
System.out.println("value= " + v);
}
}
}
六、主要實現類區別小結
1、Vector和ArrayList
1),vector是線程同步的,所以它也是線程安全的,而arraylist是線程異步的,是不安全的。如果不考慮到線程的安全因素,一般用arraylist效率比較高。
2),如果集合中的元素的數目大於目前集合數組的長度時,vector增長率爲目前數組長度的100%,而arraylist增長率爲目前數組長度的50%。如果在集合中使用數據量比較大的數據,用vector有一定的優勢。
3),如果查找一個指定位置的數據,vector和arraylist使用的時間是相同的,如果頻繁的訪問數據,這個時候使用vector和arraylist都可以。而如果移動一個指定位置會導致後面的元素都發生移動,這個時候就應該考慮到使用linklist,因爲它移動一個指定位置的數據時其它元素不移動。
ArrayList 和Vector是採用數組方式存儲數據,此數組元素數大於實際存儲的數據以便增加和插入元素,都允許直接序號索引元素,但是插入數據要涉及到數組元素移動等內存操作,所以索引數據快,插入數據慢,Vector由於使用了synchronized方法(線程安全)所以性能上比ArrayList要差,LinkedList使用雙向鏈表實現存儲,按序號索引數據需要進行向前或向後遍歷,但是插入數據時只需要記錄本項的前後項即可,所以插入數度較快。
2、ArrayList和LinkedList
1.ArrayList是實現了基於動態數組的數據結構,LinkedList基於鏈表的數據結構。
2.對於隨機訪問get和set,ArrayList覺得優於LinkedList,因爲LinkedList要移動指針。
3.對於新增和刪除操作add和remove,LinedList比較佔優勢,因爲ArrayList要移動數據。 這一點要看實際情況的。若只對單條數據插入或刪除,ArrayList的速度反而優於LinkedList。但若是批量隨機的插入刪除數據,LinkedList的速度大大優於ArrayList. 因爲ArrayList每插入一條數據,要移動插入點及之後的所有數據。
3、HashMap與TreeMap
1、 HashMap通過hashcode對其內容進行快速查找,而TreeMap中所有的元素都保持着某種固定的順序,如果你需要得到一個有序的結果你就應該使用TreeMap(HashMap中元素的排列順序是不固定的)。
2、在Map 中插入、刪除和定位元素,HashMap是最好的選擇。但如果您要按自然順序或自定義順序遍歷鍵,那麼TreeMap會更好。使用HashMap要求添加的鍵類明確定義了hashCode()和 equals()的實現。
兩個map中的元素一樣,但順序不一樣,導致hashCode()不一樣。
同樣做測試:
在HashMap中,同樣的值的map,順序不同,equals時,false;
而在treeMap中,同樣的值的map,順序不同,equals時,true,說明,treeMap在equals()時是整理了順序了的。
HashTable與HashMap
1、同步性:Hashtable是線程安全的,也就是說是同步的,而HashMap是線程序不安全的,不是同步的。
2、HashMap允許存在一個爲null的key,多個爲null的value 。
3、hashtable的key和value都不允許爲null。