寫(xiě)在前面:
這是一篇菜鳥(niǎo)的學(xué)習(xí)筆記蛋勺。
容器的簡(jiǎn)圖
不包含抽象類(lèi)和遺留構(gòu)件
Java 容器類(lèi)類(lèi)庫(kù)的用途是“保存對(duì)象”脱吱。
Java 容器類(lèi)都可以自動(dòng)地調(diào)整自己的尺寸缴阎。
Java 容器可劃分為兩個(gè)不同的概念: Collection 與 Map只磷。
1.Collection里面的接口有些是可選的(為了防止接口爆炸的情況)蝙斜,并且未獲支持的操作只有在運(yùn)行時(shí)才能探測(cè)到名惩,因此有可能調(diào)用接口時(shí)會(huì)獲取到UnsupportedOperationException。
List
1.List 接口在 Collection 的基礎(chǔ)上添加了大量的方法孕荠。
ArrayList
1.底層是數(shù)組LinkedList
1.底層是鏈表
2.各種Queue和棧的行為由LinkedList提供支持娩鹉。
3.一些方法需要注意:
// 不移除
getFirst()攻谁、element()// 返回列表的頭,如果List為空拋出NoSuchElemetException底循。
peek() // 返回列表的頭巢株,如果List為空返回null。
// 移除
removeFirst()熙涤、remove()// 移除并返回列表的頭阁苞,如果List為空拋出NoSushElementException。
poll()// 移除并返回列表的頭祠挫,如果List為空返回null那槽。
Stack
如果你只需要棧的行為,那么使用繼承LinkedList就不合適了等舔,因?yàn)檫@樣會(huì)產(chǎn)生具有LinkedList的其他所有方法的類(lèi)(Java1.0的設(shè)計(jì)者在創(chuàng)建java.util.Stack時(shí)骚灸,就犯了這個(gè)錯(cuò)誤)。因此不使用Java原生態(tài)的Stack類(lèi)慌植,而簡(jiǎn)單封裝LinkedList來(lái)實(shí)現(xiàn)棧即可甚牲。
public class Stack<T>{
private LinkedList<T> storage = new LinkedList<T>();
public void push(T v) {
storage.addFirst(v);
}
public T peek() {
return storage.getFirst();
}
public T pop() {
return storage.removeFirst();
}
public boolean empty() {
return storage.isEmpty();
}
public String toString() {
return storage.toString();
}
}
Set
1.Set 具有與Collecion完全一樣的接口,因此沒(méi)有任何額外的功能蝶柿,兩者只是行為不同而已丈钙。
2.Set 不保存重復(fù)的元素。
HashSet
1.隨機(jī)查找最快
2.存儲(chǔ)的順序并無(wú)意義
3.元素必須定義hashCode()方法TreeSet
1.按照比較結(jié)果的升序保存對(duì)象
2.底層是紅-黑樹(shù)
3.元素必須實(shí)現(xiàn)Comparable接口LinkedHashSet
1.按照被添加的順序保存對(duì)象
2.保留HashSet的查詢(xún)速度
3.元素必須定義hashCode()方法
注:
1.此外交汤,你必須為散列存儲(chǔ)和樹(shù)型存儲(chǔ)都創(chuàng)建一個(gè)equals()方法雏赦,因?yàn)镾et容器需要通過(guò)該方法判斷元素是否重復(fù)。
2.對(duì)于良好的編程風(fēng)格而言芙扎,你應(yīng)該在覆蓋equals()方法時(shí)星岗,總是同時(shí)覆蓋hashCode()方法。
Queue
- LinkedList 提供了方法以支持隊(duì)列的行為戒洼,并且它實(shí)現(xiàn)了Queue接口俏橘,因此LinkedList可以用作Queue的一種實(shí)現(xiàn)。通過(guò)將LinkedList向上轉(zhuǎn)型為Queue:
Queue queue = new LinkedList();
事實(shí)上Queue接口窄化了對(duì)LinkedList的方法的訪(fǎng)問(wèn)權(quán)限以“專(zhuān)心”當(dāng)作隊(duì)列使用施逾。
PriorityQueue
1.排序是通過(guò)Comparable進(jìn)行控制的(添加到隊(duì)列中的元素實(shí)現(xiàn)Comparable接口)雙向隊(duì)列
1.Java標(biāo)準(zhǔn)類(lèi)庫(kù)中沒(méi)有任何顯式的用于雙向隊(duì)列的接口敷矫。但是可以和Stack一樣,通過(guò)組合LinkedList來(lái)實(shí)現(xiàn)一個(gè)Deque類(lèi)汉额。
Map
Map和Collection之間的唯一重疊就是Map可以使用entrySet()、values()方法來(lái)產(chǎn)生Collection
HashMap
1.提供最快的查找技術(shù)
2.沒(méi)有明顯的順序TreeMap
1.按照比較結(jié)果的升序保存鍵
2.唯一有subMap()方法的MapLinkedHashMap
1.按照插入順序保存鍵
2.保留了HashMap的查詢(xún)速度
3.可以在構(gòu)造器中設(shè)定LinkedHashMap實(shí)現(xiàn)最近最少使用算法榨汤,于是沒(méi)有使用過(guò)得元素就會(huì)出現(xiàn)在隊(duì)列的前面蠕搜。
LinkedHashMap linkedHashMap = new LinkedHashMap(16,0.75f,true);
WeakHashMap(弱鍵映射)
1.如果映射之外沒(méi)有引用指向某個(gè)“鍵”,則此“鍵”可以被垃圾收集器回收ConcurrentHashMap
1.一種線(xiàn)程安全的MapIdentityHashMao
1.使用==代替equals()對(duì)“鍵”進(jìn)行比較的散列映射收壕。專(zhuān)門(mén)解決特殊問(wèn)題而設(shè)計(jì)的
注:
對(duì)Map中使用的鍵的要求與對(duì)Set中的元素的要求一樣妓灌,都必須有一個(gè)equals()方法轨蛤。如果鍵被用于散列還需要hashCode(),如果鍵被用于TreeMap虫埂,那么它必須實(shí)現(xiàn)Comparable祥山。
迭代器
迭代器是一個(gè)對(duì)象,他的工作是遍歷并選擇序列中的對(duì)象掉伏,統(tǒng)一了對(duì)容器的訪(fǎng)問(wèn)方式缝呕。屬于輕量級(jí)對(duì)象。
1.如果你只是向前遍歷List斧散,并不打算修改List對(duì)象本身供常,那么你可以使用foreach語(yǔ)法更簡(jiǎn)潔。
2.如果對(duì)List要執(zhí)行一個(gè)remove等會(huì)影響容器元素個(gè)數(shù)的操作鸡捐,則使用迭代器或者for()循環(huán)栈暇。因?yàn)槭褂胒oreach()時(shí)會(huì)出現(xiàn)錯(cuò)誤。
Iterator
1.使用方法iterator()要去容器返回一個(gè)Iterator箍镜。
2.使用next()獲取序列中的下一個(gè)元素源祈。
3.使用hasNext()檢查序列中是否還有元素。
4.使用remove()將迭代器新近返回的元素刪除色迂。ListIterator
1它是更加強(qiáng)大的IIterator香缺,但是只能用于各種List類(lèi)的訪(fǎng)問(wèn)。
2.它可以雙向移動(dòng)脚草。
3.可以使用set()方法替換訪(fǎng)問(wèn)過(guò)得最后一個(gè)元素赫悄。
4.hasPrevious()、privious()方法對(duì)應(yīng)hasNext()馏慨、next()方法埂淮。
注:
1.Map 沒(méi)有iterator()方法,但是可以通過(guò)如下方法遍歷:
for(Map.Entry e: m.entrySet()){
e.getKey();
e.getValue();
}
Collection 與 Iterator
- 使用接口描述的一個(gè)理由是它可以使我們能夠創(chuàng)建更通用的代碼写隶。
- 用迭代器而不是Collection來(lái)表示容器之間的共性倔撞。
但是Java中將這兩種方法綁定到了一起,實(shí)現(xiàn)Collection就意味著需要提供iterator()方法慕趴。
設(shè)想這種情況:
如果你的類(lèi)已經(jīng)繼承了其他的類(lèi)痪蝇,那么你就不再繼承AbstractCollection了。在這種情況下冕房,要實(shí)現(xiàn)Collection躏啰,就必須實(shí)現(xiàn)該接口中的所以方法。此時(shí)耙册,繼承并提供創(chuàng)建迭代器的能力就會(huì)顯得容易得多了给僵。
Foreach與迭代器
foreach語(yǔ)法主要用于數(shù)組,但是它也可以應(yīng)用于任何Collection對(duì)象。之所以Collection對(duì)象能夠使用于foreach帝际,是因?yàn)镮terable接口蔓同。因此任何實(shí)現(xiàn)Iterable的類(lèi)都可以將它用于foreach語(yǔ)句中。
- 不存在任何從數(shù)組到Iterator的自動(dòng)轉(zhuǎn)換蹲诀,因此必須手工執(zhí)行轉(zhuǎn)換:
String[] strings;
Arrays.asList(strings);
其他一些記錄
Arrays.asList()產(chǎn)生的List對(duì)象會(huì)使用底層數(shù)組作為其物理實(shí)現(xiàn)斑粱,不能對(duì)數(shù)組嘗試改變長(zhǎng)度的操作。如果你執(zhí)行的操作會(huì)修改這個(gè)List脯爪,并且你不想原來(lái)的數(shù)組被修改则北,那么就應(yīng)該在另一個(gè)容器中創(chuàng)建副本。
打亂Collection元素順序
Collections.shuffle(list,rand);
- 數(shù)據(jù)傳輸對(duì)象(或信使)寫(xiě)法:
// 將域定義為public披粟、final即可
public final K key;
public final V value;
正確的equals()方法必須滿(mǎn)足下列5個(gè)條件:
1.自反性
2.對(duì)稱(chēng)性
3.傳遞性
4.一致性
5對(duì)任何不適null的x咒锻,x.equals(null)一定返回falsehashCode生成方法:
1.給int變量result賦予某個(gè)非零參量
2.為對(duì)象內(nèi)每個(gè)有意義的域計(jì)算出一個(gè)int散列碼c
3.合并計(jì)算得到散列嗎
result = 37 * result + c;
4.返回result
5.檢查hashCode()最后的生成結(jié)果
6.例如:
int result = 17;
result = 37 * result + s.hashCode();
result = 37 * result + id;
return result;