這段時間一直在總結(jié)過去的知識融虽,今天來總結(jié)一下Java中常用的集合有额,在工作中使用最多的可能就在這里
下面來看下Java集合中總的框架結(jié)構(gòu)
Collection系列
Map系列
這張圖可以很好的了解各個集合之間的關(guān)系
下面是最常用的集合
Java集合大致可以分為Set、List笋熬、Queue和Map四種體系
1, Set代表無序胳螟、不可重復(fù)的集合;
2, List代表有序秘遏、重復(fù)的集合;
3, Map則代表具有映射關(guān)系的集合;
4, Java 5 又增加了Queue體系集合舍扰,代表一種隊(duì)列集合實(shí)現(xiàn)
下面開始分別介紹四大派系
Set系列
Collection是父接口,Set,Queue,List都是繼承Collection接口的陵且。
HashSet
HashSet是Set接口的實(shí)現(xiàn)類慕购,它實(shí)現(xiàn)了Set接口中的所有方法沪悲,并沒有添加額外的方法,大多數(shù)時候使用Set集合時就是使用這個實(shí)現(xiàn)類阱表。
特點(diǎn)
1,HashSet按Hash算法來存儲集合中的元素,因此具有很好的存取和查找性能殿如。
2,不可以存放重復(fù)元素,元素存取是無序的
3,集合元素值可以是null固歪。
4, HashSet不是同步的。因此是多線程訪問時必須通過代碼來同步
4, HashSet集合判斷兩個元素相等的標(biāo)準(zhǔn)是兩個對象通過equals()方法比較相等,并且兩個對象的hashCode()方法返回值也相等
注意:HashSet底層是HashMap實(shí)現(xiàn)的溉箕,HashSet的所有集合元素,構(gòu)成了HashMap的key,其value為一個靜態(tài)Object對象。因此HashSet的所有性質(zhì),HashMap的key所構(gòu)成的集合都具備
List 集合
List是一個元素有序、可重復(fù)的集合幅垮,集合中每個元素都有其對應(yīng)的順序索引潮峦。
ArrayList和Vector
ArrayList和Vector都是List實(shí)現(xiàn)類分苇。
ArrayList和Vector類封裝了一個動態(tài)的盆偿、允許再分配的Object[]數(shù)組罐农。ArrayList或Vector對象使用initalCapacity參數(shù)來設(shè)置該數(shù)組的長度麸恍,當(dāng)向ArrayList或Vector中添加元素超過了該數(shù)組的長度時逝薪,它們的initalCapacity會自動增加欢搜。
因此 ArrayList是一個動態(tài)擴(kuò)展的數(shù)組缘琅,Vector也同樣如此
ArrayList和Vector的區(qū)別
1, ArrayList是線程不安全的受啥,Vector是線程安全的。
2, Vector的性能比ArrayList差
LinkedList
LinkedList類也是List的實(shí)現(xiàn)類,so可以根據(jù)索引來隨機(jī)訪問集合中的元素。除此之外,LinkedList還實(shí)現(xiàn)了Deque接口,可以被當(dāng)作成雙端隊(duì)列來使用
注意:==LinkedList底層的數(shù)據(jù)結(jié)構(gòu)是鏈表結(jié)構(gòu)==
基于鏈表特性,新增的一些方法
/**
* 將指定元素插入此列表的開頭惭嚣。
*/
public void addFirst(E e) {
throw new RuntimeException("Stub!");
}
/**
* 將指定元素添加到此列表的結(jié)尾载矿。
*/
public void addLast(E e) {
throw new RuntimeException("Stub!");
}
/**
* 返回此列表的第一個元素
*/
public E getFirst() {
throw new RuntimeException("Stub!");
}
/**
* 返回此列表的最后一個元素
*/
public E getLast() {
throw new RuntimeException("Stub!");
}
/**
* 在此列表的開頭插入指定的元素
*/
public boolean offerFirst(E e) {
throw new RuntimeException("Stub!");
}
/**
* 在此列表末尾插入指定的元素
*/
public boolean offerLast(E e) {
throw new RuntimeException("Stub!");
}
/**
* 獲取但不移除此列表的第一個元素;如果此列表為空,則返回 null
*/
public E peekFirst() {
throw new RuntimeException("Stub!");
}
/**
* 獲取但不移除此列表的最后一個元素句占;如果此列表為空杨拐,則返回 null舱痘。
*/
public E peekLast() {
throw new RuntimeException("Stub!");
}
/**
* 獲取并移除此列表的第一個元素翎猛;如果此列表為空鹃两,則返回 null
*/
public E pollFirst() {
throw new RuntimeException("Stub!");
}
/**
* 獲取并移除此列表的最后一個元素梯醒;如果此列表為空,則返回 null
*/
public E pollLast() {
throw new RuntimeException("Stub!");
}
/**
* 移除并返回此列表的第一個元素极景。
*/
public E removeFirst() {
throw new RuntimeException("Stub!");
}
/**
* 移除并返回此列表的最后一個元素
*/
public E removeLast() {
throw new RuntimeException("Stub!");
}
/**
* 從此列表中移除第一次出現(xiàn)的指定元素(從頭部到尾部遍歷列表時)
*/
public boolean removeFirstOccurrence(Object o) {
throw new RuntimeException("Stub!");
}
/**
* 從此列表中移除最后一次出現(xiàn)的指定元素(從頭部到尾部遍歷列表時)
*/
public boolean removeLastOccurrence(Object o) {
throw new RuntimeException("Stub!");
}
集合 | 數(shù)組結(jié)構(gòu) | 線程安全 | 性能 | 使用場景 |
---|---|---|---|---|
List | 需要保留存儲順序, 并且保留重復(fù)元素, 使用List | |||
ArrayList | 動態(tài)數(shù)組 | 非線程安全 | 隨機(jī)訪問元素性能出色 | 查詢較多, 使用ArrayList |
Vector | 動態(tài)數(shù)組 | 線程安全 | 比ArrayList差 | 需要線程安全稍途,使用Vector |
LinkList | 鏈表 | 非線程安全 | 在插入、刪除元素時性能比較出色但隨機(jī)訪問集合元素時性能較差 | 存取較多,使用LinkedList |
Queue集合
Queue用戶模擬隊(duì)列這種數(shù)據(jù)結(jié)構(gòu)共屈,隊(duì)列通常是指“先進(jìn)先出”(FIFO,first-in-first-out)的容器班缎。隊(duì)列的頭部是在隊(duì)列中存放時間最長的元素,隊(duì)列的尾部是保存在隊(duì)列中存放時間最短的元素。新元素插入(offer)到隊(duì)列的尾部蹂随,訪問元素(poll)操作會返回隊(duì)列頭部的元素乒躺。通常娜遵,隊(duì)列不允許隨機(jī)訪問隊(duì)列中的元素
PriorityQueue
- PriorityQueue是Queue的實(shí)現(xiàn)類万皿,本質(zhì)也是一個動態(tài)數(shù)組位岔,在這一方面與ArrayList是一致的。
- PriorityQueue中的元素可以默認(rèn)自然排序(也就是數(shù)字默認(rèn)是小的在隊(duì)列頭巾遭,字符串則按字典序排列)或者通過提供的Comparator(比較器)在隊(duì)列實(shí)例化時指定的排序方式
特點(diǎn):
PriorityQueue保存隊(duì)列元素的順序不是按加入隊(duì)列的順序末捣,而是按隊(duì)列元素的大小進(jìn)行重新排序。
所以調(diào)用peek()或pool()方法取出隊(duì)列中頭部的元素時,并不是取出最先進(jìn)入隊(duì)列的元素,而是取出隊(duì)列中的最小的元素
PriorityQueue不是線程安全的
不允許插入 null 元素
接下來看下Map,說到Map當(dāng)然離不開他的兩個重要的實(shí)現(xiàn)類HashMap和Hashtable
Map集合存放具有映射關(guān)系的數(shù)據(jù),
因此Map集合里保存著兩組數(shù)骗灶,一組值中保存Map里的key,另一組值中保存Map里的value移迫,key和value都可以是任何引用類型的數(shù)據(jù)。
特點(diǎn):Map的key不允許重復(fù)机杜,即同一個Map對象中任何兩個key通過equals方法比較返回的一定是false
HashMap
HashMap 是一個散列表蚀苛,它存儲的內(nèi)容是鍵值對(key-value)映射。
理解HashMap本質(zhì)
public HashMap() {
throw new RuntimeException("Stub!");
}
public HashMap(int initialCapacity) {
throw new RuntimeException("Stub!");
}
public HashMap(int initialCapacity, float loadFactor) {
throw new RuntimeException("Stub!");
}
public HashMap(Map<? extends K, ? extends V> m) {
throw new RuntimeException("Stub!");
}
構(gòu)造函數(shù)中有兩個重要的參數(shù):容量大小(initialCapacity)和加載因子(loadFactor)
容量(initialCapacity)是: 哈希表的容量膘怕,初始容量是哈希表在創(chuàng)建時的容量(即DEFAULT_INITIAL_CAPACITY = 1 << 4)
加載因子(loadFactor): 是哈希表在其容量自動增加之前可以達(dá)到多滿的一種尺度。當(dāng)哈希表中的條目數(shù)超出了加載因子與當(dāng)前容量的乘積時,則要對該哈希表進(jìn)行 resize操作(即重建內(nèi)部數(shù)據(jù)結(jié)構(gòu))垦缅,從而哈希表將具有大約兩倍的桶數(shù)。默認(rèn)加載因子是 0.75(即DEFAULT_LOAD_FACTOR = 0.75f),
注:
HashMap是通過"拉鏈法"實(shí)現(xiàn)的哈希表赢底。它包括幾個重要的成員變量:table, size, threshold, loadFactor失都。
table是一個Node[]數(shù)組類型柏蘑,而Node實(shí)際上就是一個單向鏈表幸冻。哈希表的"key-value鍵值對"都是存儲在Node數(shù)組中的。
size是HashMap的大小咳焚,它是HashMap保存的鍵值對的數(shù)量洽损。
threshold是HashMap的閾值,用于判斷是否需要調(diào)整HashMap的容量革半。threshold的值="容量*加載因子"碑定,當(dāng)HashMap中存儲數(shù)據(jù)的數(shù)量達(dá)到threshold時,就需要將HashMap的容量加倍又官。
loadFactor 為加載因子
HashMap遍歷方式
Map<Integer, String> map = new HashMap<>();
map.put(1, "acfgdws");
map.put(2, "bwdfrx");
map.put(3, "abrgcs");
map.put(4, "absrfgr");
map.put(5, "abcderf");
/**
* 第一種:通過Map.keySet遍歷key和value
*/
for (Integer key : map.keySet()) { //map.keySet()返回的是所有key的值
String str = map.get(key);//得到每個key多對用value的值
Log.d("Map", key + " " + str);
}
/**
*第二種:通過Map.entrySet使用iterator遍歷key和value
*/
Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Integer, String> entry = it.next();
Log.d("Map", "key= " + entry.getKey() + " and value= " + entry.getValue());
}
/** 第三種:推薦延刘,尤其是容量大時 通過Map.entrySet遍歷key和value
Map.entry<Integer,String> 映射項(xiàng)(鍵-值對)
map.entrySet() 返回此映射中包含的映射關(guān)系的 Set視圖。
*/
for (Map.Entry<Integer, String> entry : map.entrySet()) {
Log.d("Map", "key= " + entry.getKey() + " and value= " + entry.getValue());
}
/**
* 第四種:通過Map.values()遍歷所有的value六敬,但不能遍歷key
*/
for (String v : map.values()) {
Log.d("Map", "value= " + v);
}
Hashtable
是一個散列表碘赖,它存儲的內(nèi)容是鍵值對(key-value)映射
構(gòu)造函數(shù)
public Hashtable() {
throw new RuntimeException("Stub!");
}
public Hashtable(int initialCapacity) {
throw new RuntimeException("Stub!");
}
public Hashtable(int initialCapacity, float loadFactor) {
throw new RuntimeException("Stub!");
}
public Hashtable(Map<? extends K, ? extends V> t) {
throw new RuntimeException("Stub!");
}
從構(gòu)造函數(shù)可以看出和HashMap一樣有兩個重要的參數(shù):容量大小(initialCapacity)和加載因子(loadFactor)
遍歷方式
Hashtable<String, Integer> table = new Hashtable<>();
table.put("a", 10);
table.put("b", 20);
table.put("c", 30);
table.put("d", 40);
/**
* 方式1: 鍵值對遍歷entrySet()
*/
for (Map.Entry<String, Integer> entry : table.entrySet()) {
String key = entry.getKey();
int value = entry.getValue();
Log.d("Hashtable", "entrySet:" + key + " " + value);
}
/***
* 方式2: key鍵的遍歷
*/
for (String key : table.keySet()) {
int value = table.get(key);
Log.d("Hashtable", "keySet:" + key + " " + value);
}
/**
* 方式3: 通過Enumeration來遍歷Hashtable
*/
Enumeration<String> enu = table.keys();
while (enu.hasMoreElements()) {
Log.d("Hashtable", "Enumeration:" + table.keys() + " " + enu.nextElement());
}
HashMap與Hashtable的區(qū)別
集合類型 | 數(shù)據(jù)結(jié)構(gòu) | 基類 | 線程安全 | 性能 | key或value是否可以為null |
---|---|---|---|---|---|
HashMap | 哈希表來存儲鍵值對 | AbstractMap | 線程安全 | 比Hashtable性能好 | 可以 |
Hashtable | 哈希表來存儲鍵值對 | Dictionary | 不安全 | 多個線程訪問同一個map性能好 | 不可以 |
注:
Dictionary是什么?它是任何可將鍵映射到相應(yīng)值的類的抽象父類,而AbstractMap是基于Map接口的骨干實(shí)現(xiàn)普泡,它以最大限度地減少實(shí)現(xiàn)此接口所需的工作