1.為什么要用集合類
Java編程思想中指出:
通常窘疮,程序總是根據(jù)運(yùn)行時(shí)才知道的某些條件去創(chuàng)建新對象。
在此之前,不會(huì)知道所需對象的數(shù)量烙常,甚至不知道確切的類型旅择。
為解決這個(gè)普遍的編程問題,需要在任意時(shí)刻和任意位置創(chuàng)建任意數(shù)量的對象戏阅。
所以橙凳,就不能依靠創(chuàng)建命名的引用來持有每一個(gè)對象:
MyType aReference;
因?yàn)槟悴恢缹?shí)際上會(huì)需要多少這樣的引用。
大多數(shù)語言都提供某種方法來解決這個(gè)基本問題彭羹。Java有多種方式保存對象(應(yīng)該說是對象的引用)黄伊。例如前面曾經(jīng)學(xué)習(xí)過的數(shù)組,它是編譯器支持的類型派殷。數(shù)組是保存一組對象的最有效的方式还最,如果你想保存一組基本類型數(shù)據(jù),也推薦使用這種方式毡惜。但是數(shù)組具有固定的尺寸拓轻, 而在更一般的情況中,你在寫程序時(shí)并不知道將需要多少個(gè)對象经伙,或者是否需要更復(fù)雜的方式來存儲(chǔ)對象扶叉,因此數(shù)組尺寸固定這一限制顯得過于受限了。
Java實(shí)用類庫還提供了一套相當(dāng)完整的容器類來解決這個(gè)問題帕膜。
其中基本的類型是List辜梳、Set、Queue和Map泳叠。這些對象類型也稱為集合類作瞄,但由于Java的類庫中使用了Collection這個(gè)名字來指代該類庫的一個(gè)特殊子集,所以我使用了范圍更廣的術(shù)語“容器”稱呼它們危纫。
解讀:
-
Java保存對象的方式有:
數(shù)組【可以保存基本類型數(shù)據(jù)宗挥;數(shù)組尺寸固定;只能存儲(chǔ)同一種類型的對象】
集合類【不可以保存基本類型數(shù)據(jù)种蝶;在根本上都是數(shù)組契耿,只是可以動(dòng)態(tài)改變數(shù)組的大小螃征;結(jié)合泛型可以存儲(chǔ)多種類型的對象】
Java中的容器指Collection搪桂、Map的統(tǒng)稱
容器中存儲(chǔ)的是對象的引用不是對象的值;數(shù)組在存儲(chǔ)基本數(shù)據(jù)類型時(shí)是存儲(chǔ)的對象的值
為什么使用集合? 可以封裝一組對象的操作盯滚,降低編程難度踢械,增加代碼復(fù)用性,提高程序運(yùn)行速度與質(zhì)量魄藕。
2.集合中的概念
Java容器類類庫的用途是“保存對象”内列,并將其劃分為兩個(gè)不同的概念:
- Collection。一個(gè)獨(dú)立元素的序列背率,這些元素都服從一條或多條規(guī)則话瞧。List必須按照插入的順序保存元素嫩与,而Set不能有重復(fù)元素。Queue按照排隊(duì)規(guī)則來確定對象產(chǎn)生的順序(通常與它們被插入的順序相同)交排。
- Map划滋。一組成對的“鍵值對”對象,允許你使用鍵來査找值埃篓。ArrayList允許你使用數(shù)字 來査找值处坪,因此在某種意義上講,它將數(shù)字與對象關(guān)聯(lián)在了一起都许。映射表允許我們使用另一個(gè) 對象來査找某個(gè)對象稻薇,它也被稱為“關(guān)聯(lián)數(shù)組”嫂冻,因?yàn)樗鼘⒛承ο笈c另外一些對象關(guān)聯(lián)在了一 起胶征,或者被稱為“字典”,因?yàn)槟憧梢允褂面I對象來査找值對象桨仿,就像在字典中使用單詞來定義 一樣睛低。Map是強(qiáng)大的編程工具。
什么是集合框架服傍?
集合框架是一個(gè)代表钱雷、操作集合的統(tǒng)一架構(gòu)。所有的集合框架都包含以下幾點(diǎn):
接口:表示集合的抽象數(shù)據(jù)類型吹零。接口允許我們操作集合時(shí)不必關(guān)注具體實(shí)現(xiàn)罩抗,從而達(dá)到“多態(tài)”。在面向?qū)ο缶幊陶Z言中灿椅,接口通常用來形成規(guī)范套蒂。
實(shí)現(xiàn)類:集合接口的具體實(shí)現(xiàn),是重用性很高的數(shù)據(jù)結(jié)構(gòu)茫蛹。
算法:用來根據(jù)需要對實(shí)體類中的對象進(jìn)行計(jì)算操刀,比如查找,排序婴洼。 同一種算法可以對不同的集合實(shí)現(xiàn)類進(jìn)行計(jì)算骨坑,這是利用了“多態(tài)”。重用性很高柬采。
3.集合的分類
Collection接口及其常用實(shí)現(xiàn)
Map接口及其常用實(shí)現(xiàn)
附帶Java集合最全結(jié)構(gòu)展示圖
4.常用集合類與對應(yīng)數(shù)據(jù)結(jié)構(gòu)
集合類是Java數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn)欢唾。所以,從數(shù)據(jù)結(jié)構(gòu)層面對比下集合類粉捻。
集合 | 接口/類 | 說明 |
---|---|---|
Collection | 接口 | 定義了集合的基本方法, |
List | 接口 | 元素有序匈辱,元素可重復(fù)。主要實(shí)現(xiàn)類:ArrayList杀迹,LinkedList亡脸,Vector押搪。 |
Vector | 類 | 線性表的數(shù)組實(shí)現(xiàn) |
Stack | 類 | 棧,Last in first out浅碾,繼承自Vector |
ArrayList | 類 | 動(dòng)態(tài)數(shù)組,源碼底層維護(hù)著List的容量與實(shí)際長度 |
LinkedList | 類 | 雙向鏈表大州,此外它還實(shí)現(xiàn)了Deque,即也實(shí)現(xiàn)了Queue |
Queue | 接口 | 隊(duì)列垂谢,F(xiàn)irst in first out |
Deque | 接口 | 雙向隊(duì)列厦画,Deque繼承自Queue,并增加了首尾兩端的進(jìn)出隊(duì)列操作 |
Map | 接口 | 一組元素結(jié)構(gòu)為K滥朱、V型的集 |
HashMap | 類 | 哈希數(shù)組+鏈表根暑,通過哈希函數(shù)能夠快速地找到元素,無沖突的情況下僅需訪問一次 ;1.8后哈希數(shù)組+鏈表+紅黑樹 |
HashTable | 類 | HashTable與HashMap的區(qū)別是其線程安全徙邻,同時(shí)它不允許K排嫌、V為null |
TreeMap | 類 | Map的二叉平衡樹實(shí)現(xiàn),根據(jù)K的hashcode排序 |
ConcurrentHashMap | 類 | 線程安全的HashMap缰犁,HashTable的替代者 |
Set | 接口 | 元素?zé)o序淳地,元素不重復(fù)。主要實(shí)現(xiàn)類:HashSet帅容,TreeSet颇象,LinkedHashSet。 |
HashSet | 類 | 內(nèi)部使用HashMap實(shí)現(xiàn)并徘,K對應(yīng)E遣钳,V保存了一個(gè)Object |
TreeSet | 類 | 內(nèi)部由TreeMap實(shí)現(xiàn),K對應(yīng)E麦乞,V保存了一個(gè)Object |
LinkedHashSet | 類 | 哈希表和鏈表的結(jié)合蕴茴,且是一個(gè)雙向鏈表;不重復(fù)且同時(shí)具有可預(yù)測的迭代順序 |
5.容器操作使用
Collection增刪改查與遍歷
作為集合的一個(gè)根接口,定義了一組對象和它的子類可以實(shí)現(xiàn)的方法:
對集合的基礎(chǔ)操作路幸,比如 :
int size() 獲取元素個(gè)數(shù)
boolean isEmpty() 是否個(gè)數(shù)為 0
boolean contains(Object element) 是否包含指定元素
boolean add(E element) 添加元素荐开,成功時(shí)返回 true
boolean remove(Object element) 刪除元素,成功時(shí)返回 true
Iterator<E> iterator() 獲取迭代器
還有一些操作整個(gè)集合的方法简肴,比如 :
boolean containsAll(Collection<?> c) 是否包含指定集合 c 的全部元素
boolean addAll(Collection<? extends E> c) 添加集合 c 中所有的元素到本集合中晃听,如果集合有改變就返回 true
boolean removeAll(Collection<?> c) 刪除本集合中和 c 集合中一致的元素,如果集合有改變就返回 true
boolean retainAll(Collection<?> c) 保留本集合中 c 集合中兩者共有的砰识,如果集合有改變就返回 true
void clear() 刪除所有元素
還有對數(shù)組操作的方法:
Object[] toArray() 返回一個(gè)包含集合中所有元素的數(shù)組
<T> T[] toArray(T[] a) 返回一個(gè)包含集合中所有元素的數(shù)組能扒,運(yùn)行時(shí)根據(jù)集合元素的類型指定數(shù)組的類型
在 JDK 8 以后,Collection 接口還提供了從集合獲取連續(xù)的或者并行流:
Stream<E> stream()
Stream<E> parallelStream()
List接口與Set接口實(shí)現(xiàn)Collection接口常用的方法有:
List接口
List接口下的集合元素存儲(chǔ)有序辫狼,可以重復(fù)初斑。
List的特有功能
A:添加功能
void add(int index, Object obj):在指定位置添加元素
B:刪除功能
Object remove(int index):根據(jù)指定索引刪除元素,并把刪除的元素返回膨处。
C:修改功能
Object set(int index, Object obj):把指定索引位置的元素修改為指定的值见秤,返回修改前的值砂竖。
D:獲取功能
int indexOf(Object o):返回指定元素在集合中第一次出現(xiàn)的索引
Object get(int index):獲取指定位置的元素
ListIterator listIterator():列表迭代器
E:截取功能
List subList(int fromIndex, int toIndex):截取集合。
Set 接口
Set接口下的元素?zé)o序鹃答,不可以重復(fù)乎澄。其下面常用有HashSet和TreeSet。
HashSet
底層數(shù)據(jù)結(jié)構(gòu)是哈希表测摔,線程不安全置济,效率高。
保證唯一性依賴兩個(gè)方法:hashCode()和equals()锋八。
順序:
判斷hashCode()值是否相同浙于。
相同:繼續(xù)走equals(),看返回值
如果true:就不添加到集合。
如果false:就添加到集合挟纱。
不同:就添加到集合羞酗。
TreeSet
底層數(shù)據(jù)結(jié)構(gòu)是二叉樹,線程不安全樊销,效率高整慎。
保證元素唯一性的方法時(shí)根據(jù)返回值是否是0脏款。
保證排序的兩種方式:
自然排序(元素具備比較性):實(shí)現(xiàn)Comparable接口
比較器排序(集合具備比較性):實(shí)現(xiàn)Comparator接口
遍歷 Collection 的幾種方式:
for-each語法
Collection<Person> persons = new ArrayList<Person>();
for (Person person : persons) {
System.out.println(person.name);
}
使用 Iterator 迭代器
Collection<Person> persons = new ArrayList<Person>();
Iterator iterator = persons.iterator();
while (iterator.hasNext) {
System.out.println(iterator.next);
}
使用 aggregate operations 聚合操作
Collection<Person> persons = new ArrayList<Person>();
persons
.stream()
.forEach(new Consumer<Person>() {
@Override
public void accept(Person person) {
System.out.println(person.name);
}
});
Map增刪改查與遍歷
map是一個(gè)鍵值對形式的集合围苫。它的元素都是有鍵和值組成。Map的鍵(key)是唯一的,值(value)可以重復(fù)撤师。
Map的功能:
A:添加功能
V put(K key ,V value) :當(dāng)key在集合中不存在是,添加元素;當(dāng)key存在時(shí)替換元素
B:判斷功能
boolean containsKey (Object key) :判斷指定的鍵是否在集合中存在
Boolean containsValue(Object value):判斷指定的值是否在集合中存在
Boolean isEmpty() :判斷集合是否為空
C:刪除功能
Void clear():清除所有鍵值對數(shù)據(jù)
D:獲取功能
Object get (Object key) :根據(jù)鍵獲取值
Set<K> keyset(): 所有鍵的集合
Collection<V>values() :所有值的集合
E:長度功能
Int size()
Map常用的有HashMap剂府、HashTable和TreeMap,遍歷常用有3種方法:
Map<String, Object>map = new HashMap<String, Object>();
map.put(“test1”, object1);
……
map.put(“testn” , objectn);
(1).Map的values()方法可以獲取Map值的集合:
Iterator it = map.values().iterator();
while(it.hasNext()){
Object obj = it.next();
}
(2).Map的keySet方法可以獲取Map鍵的Set集合:
Set<String> keys = map.keySet();
for(Iterator it = key.iterator(); it.hasNext(); ){
String key = it.next();
Object obj = map.get(key);
}
(3).通過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());
}
(4).通過Map.entrySet遍歷key和value,推薦剃盾,尤其是容量大時(shí)
for (Map.Entry<Integer, String> entry : map.entrySet()) {
//entry.getKey() ;entry.getValue();
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}