Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap
Collection接口
Collection是最基本的集合接口寨昙,一個(gè)Collection代表一組Object,即Collection的元素(Elements)何暮。Java SDK不提供直接繼承自Collection的類,Java SDK提供的類都是繼承自Collection的“子接口”如List和Set炊甲。
所有實(shí)現(xiàn)Collection接口的類都必須提供兩個(gè)標(biāo)準(zhǔn)的構(gòu)造函數(shù):無參數(shù)的構(gòu)造函數(shù)用于創(chuàng)建一個(gè)空的Collection俭缓,有一個(gè) Collection參數(shù)的構(gòu)造函數(shù)用于創(chuàng)建一個(gè)新的Collection,這個(gè)新的Collection與傳入的Collection有相同的元素钙蒙。后一個(gè)構(gòu)造函數(shù)允許用戶復(fù)制一個(gè)Collection福扬。
如何遍歷Collection中的每一個(gè)元素腕铸?不論Collection的實(shí)際類型如何,它都支持一個(gè)iterator()的方法铛碑,該方法返回一個(gè)迭代子狠裹,使用該迭代子即可逐一訪問Collection中每一個(gè)元素。典型的用法如下:
Iterator it = collection.iterator(); // 獲得一個(gè)迭代子
while(it.hasNext()) {
Object obj = it.next(); // 得到下一個(gè)元素
}
由Collection接口派生的兩個(gè)接口是List和Set汽烦。
讓我們轉(zhuǎn)到對(duì)框架實(shí)現(xiàn)的研究涛菠,具體的集合類遵循命名約定,并將基本數(shù)據(jù)結(jié)構(gòu)和框架接口相結(jié)合撇吞。除了四個(gè)歷史集合類外俗冻,Java 2 框架還引入了六個(gè)集合實(shí)現(xiàn),如下表所示梢夯。關(guān)于歷史集合類如何轉(zhuǎn)換言疗、比如說晴圾,如何修改Hashtable 并結(jié)合到框架中颂砸,請(qǐng)參閱歷史集合類 。
接口 實(shí)現(xiàn) 歷史集合類
Set HashSet
TreeSet
List ArrayList Vector
LinkedList Stack
Map HashMap Hashtable
TreeMap Properties
這里沒有 Collection 接口的實(shí)現(xiàn)。歷史集合類人乓,之所以這樣命名是因?yàn)閺?Java 類庫(kù) 1.0 發(fā)行版就開始沿用至今了勤篮。
如果從歷史集合類轉(zhuǎn)換到新的框架類,主要差異之一在于所有的操作都和新類不同步色罚。您可以往新類中添加同步的實(shí)現(xiàn)碰缔,但您不能把它從舊的類中除去。
Collection collection = new ArrayList();(這樣寫的好處在于戳护,以后如果要理性不同的集合金抡,可以省略很多麻煩。因?yàn)槎际怯肅ollection接口里的方法腌且,)
boolean add(E o)
? ? ? ? ? 確保此 collection 包含指定的元素(可選操作)梗肝。
boolean addAll(Collection<? extends E> c)
? ? ? ? ? 將指定 collection 中的所有元素都添加到此 collection 中(可選操作)。
void clear()
? ? ? ? ? 移除此 collection 中的所有元素(可選操作)铺董。
boolean contains(Object o)
? ? ? ? ? 如果此 collection 包含指定的元素巫击,則返回 true。
boolean containsAll(Collection<?> c)
? ? ? ? ? 如果此 collection 包含指定 collection 中的所有元素精续,則返回true坝锰。
boolean equals(Object o)
? ? ? ? ? 比較此 collection 與指定對(duì)象是否相等。
int hashCode()
? ? ? ? ? 返回此 collection 的哈希碼值重付。
boolean isEmpty()
? ? ? ? ? 如果此 collection 不包含元素顷级,則返回 true。
Iterator<E> iterator()
? ? ? ? ? 返回在此 collection 的元素上進(jìn)行迭代的迭代器堪夭。
boolean remove(Object o)
? ? ? ? ? 從此 collection 中移除指定元素的單個(gè)實(shí)例愕把,如果存在的話(可選操作)。
boolean removeAll(Collection<?> c)
? ? ? ? ? 移除此 collection 中那些也包含在指定 collection 中的所有元素(可選操作)森爽。
boolean retainAll(Collection<?> c)
? ? ? ? ? 僅保留此 collection 中那些也包含在指定 collection 的元素(可選操作)恨豁。
int size()
? ? ? ? ? 返回此 collection 中的元素?cái)?shù)。
Object[] toArray()
? ? ? ? ? 返回包含此 collection 中所有元素的數(shù)組爬迟。
<T> T[] toArray(T[] a)
? ? ? ? ? 返回包含此 collection 中所有元素的數(shù)組橘蜜;返回?cái)?shù)組的運(yùn)行時(shí)類型與指定數(shù)組的運(yùn)行時(shí)類型相同。
*All方法參數(shù)的類型都為Collection 付呕,大多數(shù)方法都是返回boolean類型值计福,Collection 接口用于表示任何對(duì)象或元素組。想要盡可能以常規(guī)方式處理一組元素時(shí)徽职,就使用這一接口象颖。(如,可以直接add(100)姆钉,可以是普通數(shù)據(jù)類型)说订。
容器類對(duì)象在調(diào)用remove,contains等方法時(shí)需要比較對(duì)象是否相等地抄瓦,這會(huì)涉及到對(duì)象類型的equals方法和hashcode方法。即陶冷,相等的對(duì)象應(yīng)該有相等的hashcode.當(dāng)然钙姊,如果是自定義的類型,需要重寫這兩個(gè)方法埂伦。
iterator接口
boolean hasNext()
? ? ? ? ? 如果仍有元素可以迭代煞额,則返回 true。
E next()
? ? ? ? ? 返回迭代的下一個(gè)元素沾谜。
void remove()
? ? ? ? ? 從迭代器指向的集合中移除迭代器返回的最后一個(gè)元素(可選操作)膊毁。
Set
Set接口同樣是Collection接口的一個(gè)子接口,它表示數(shù)學(xué)意義上的集合概念基跑。Set中不包含重復(fù)的元素媚媒,即Set中不存兩個(gè)這樣的元素e1和e2,使得e1.equals(e2)為true涩僻。由于Set接口提供的數(shù)據(jù)結(jié)構(gòu)是數(shù)學(xué)意義上集合概念的抽象缭召,因此它需要支持對(duì)象的添加、刪除逆日,而不需提供隨機(jī)訪問嵌巷。故Set接口與Collection的接口相同,在此對(duì)里面的方法不作介紹室抽。
boolean add(E o)
? ? ? ? ? 如果 set 中尚未存在指定的元素搪哪,則添加此元素(可選操作)。
boolean addAll(Collection<? extends E> c)
? ? ? ? ? 如果 set 中沒有指定 collection 中的所有元素坪圾,則將其添加到此 set 中(可選操作)晓折。
void clear()
? ? ? ? ? 移除 set 中的所有元素(可選操作)。
boolean contains(Object o)
? ? ? ? ? 如果 set 包含指定的元素兽泄,則返回 true漓概。
boolean containsAll(Collection<?> c)
? ? ? ? ? 如果此 set 包含指定 collection 的所有元素,則返回 true病梢。
boolean equals(Object o)
? ? ? ? ? 比較指定對(duì)象與此 set 的相等性胃珍。
int hashCode()
? ? ? ? ? 返回 set 的哈希碼值。
boolean isEmpty()
? ? ? ? ? 如果 set 不包含元素蜓陌,則返回 true觅彰。
Iterator<E> iterator()
? ? ? ? ? 返回在此 set 中的元素上進(jìn)行迭代的迭代器。
boolean remove(Object o)
? ? ? ? ? 如果 set 中存在指定的元素钮热,則將其移除(可選操作)填抬。
boolean removeAll(Collection<?> c)
? ? ? ? ? 移除 set 中那些包含在指定 collection 中的元素(可選操作)。
boolean retainAll(Collection<?> c)
? ? ? ? ? 僅保留 set 中那些包含在指定 collection 中的元素(可選操作)隧期。
int size()
? ? ? ? ? 返回 set 中的元素?cái)?shù)(其容量)飒责。
Object[] toArray()
? ? ? ? ? 返回一個(gè)包含 set 中所有元素的數(shù)組蛀骇。
<T> T[] toArray(T[] a)
? ? ? ? ? 返回一個(gè)包含 set 中所有元素的數(shù)組;返回?cái)?shù)組的運(yùn)行時(shí)類型是指定數(shù)組的類型读拆。
按照定義,Set 接口繼承 Collection 接口鸵闪,而且它不允許集合中存在重復(fù)項(xiàng)檐晕。所有原始方法都是現(xiàn)成的,沒有引入新方法蚌讼。具體的Set 實(shí)現(xiàn)類依賴添加的對(duì)象的 equals()方法來檢查等同性辟灰。
HashSet 類和 TreeSet 類
“集合框架”支持 Set 接口兩種普通的實(shí)現(xiàn):HashSet 和TreeSet。在更多情況下篡石,您會(huì)使用 HashSet 存儲(chǔ)重復(fù)自由的集合芥喇。考慮到效率凰萨,添加到 HashSet 的對(duì)象需要采用恰當(dāng)分配散列碼的方式來實(shí)現(xiàn)hashCode() 方法继控。雖然大多數(shù)系統(tǒng)類覆蓋了 Object 中缺省的hashCode()實(shí)現(xiàn),但創(chuàng)建您自己的要添加到 HashSet 的類時(shí)胖眷,別忘了覆蓋 hashCode()武通。當(dāng)您要從集合中以有序的方式抽取元素時(shí),TreeSet 實(shí)現(xiàn)會(huì)有用處珊搀。為了能順利進(jìn)行冶忱,添加到TreeSet 的元素必須是可排序的。 “集合框架”添加對(duì) Comparable 元素的支持境析,在排序的“可比較的接口”部分中會(huì)詳細(xì)介紹囚枪。我們暫且假定一棵樹知道如何保持java.lang 包裝程序器類元素的有序狀態(tài)。一般說來劳淆,先把元素添加到 HashSet链沼,再把集合轉(zhuǎn)換為TreeSet 來進(jìn)行有序遍歷會(huì)更快。
為優(yōu)化 HashSet 空間的使用沛鸵,您可以調(diào)優(yōu)初始容量和負(fù)載因子忆植。TreeSet 不包含調(diào)優(yōu)選項(xiàng),因?yàn)闃淇偸瞧胶獾内司剩WC了插入朝刊、刪除、查詢的性能為log(n)蜈缤。
HashSet 和 TreeSet 都實(shí)現(xiàn) Cloneable 接口拾氓。
集的使用示例
為演示具體 Set 類的使用,下面的程序創(chuàng)建了一個(gè) HashSet底哥,并往里添加了一組名字咙鞍,其中有個(gè)名字添加了兩次房官。接著,程序把集中名字的列表打印出來续滋,演示了重復(fù)的名字沒有出現(xiàn)翰守。接著,程序把集作為TreeSet 來處理疲酌,并顯示有序的列表蜡峰。
import java.util.*;
public class SetExample {
? public static void main(String args[]) {
? ? Set set = new HashSet();
? ? set.add("Bernadine");
? ? set.add("Elizabeth");
? ? set.add("Gene");
? ? set.add("Elizabeth");
? ? set.add("Clara");
? ? System.out.println(set);
? ? Set sortedSet = new TreeSet(set);
? ? System.out.println(sortedSet);
? }
}
運(yùn)行程序產(chǎn)生了以下輸出。請(qǐng)注意重復(fù)的條目只出現(xiàn)了一次朗恳,列表的第二次輸出已按字母順序排序湿颅。
[Gene, Clara, Bernadine, Elizabeth]
[Bernadine, Clara, Elizabeth, Gene]
List 接口
List 接口繼承了 Collection 接口以定義一個(gè)允許重復(fù)項(xiàng)的有序集合。該接口不但能夠?qū)α斜淼囊徊糠诌M(jìn)行處理粥诫,還添加了面向位置的操作油航。
有序的 collection(也稱為序列)。此接口的用戶可以對(duì)列表中每個(gè)元素的插入位置進(jìn)行精確地控制怀浆。用戶可以根據(jù)元素的整數(shù)索引(在列表中的位置)訪問元素谊囚,并搜索列表中的元素。
與 set 不同执赡,列表通常允許重復(fù)的元素秒啦。更正式地說,列表通常允許滿足 e1.equals(e2) 的元素對(duì) e1 和 e2搀玖,并且如果列表本身允許 null 元素的話余境,通常它們?cè)试S多個(gè) null 元素。難免有人希望通過在用戶嘗試插入重復(fù)元素時(shí)拋出運(yùn)行時(shí)異常的方法來禁止重復(fù)的列表灌诅,但我們希望這種用法越少越好芳来。
List 接口在 iterator、add猜拾、remove即舌、equals 和 hashCode 方法的協(xié)定上加了一些其他約定,超過了 Collection 接口中指定的約定挎袜。為方便起見顽聂,這里也包括了其他繼承方法的聲明墩新。
List 接口提供了 4 種對(duì)列表元素進(jìn)行定位(索引)訪問方法趴捅。列表(像 Java 數(shù)組一樣)是基于 0 的。注意田柔,這些操作可能在和某些實(shí)現(xiàn)(例如 LinkedList 類)的索引值成比例的時(shí)間內(nèi)執(zhí)行全景。因此耀石,如果調(diào)用方不知道實(shí)現(xiàn),那么在列表元素上迭代通常優(yōu)于用索引遍歷列表爸黄。
List 接口提供了特殊的迭代器滞伟,稱為 ListIterator揭鳞,除了允許 Iterator 接口提供的正常操作外,該迭代器還允許元素插入和替換梆奈,以及雙向訪問野崇。還提供了一個(gè)方法來獲取從列表中指定位置開始的列表迭代器。
List 接口提供了兩種搜索指定對(duì)象的方法亩钟。從性能的觀點(diǎn)來看乓梨,應(yīng)該小心使用這些方法。在很多實(shí)現(xiàn)中径荔,它們將執(zhí)行高開銷的線性搜索。
List 接口提供了兩種在列表的任意位置高效插入和移除多個(gè)元素的方法脆霎。
注意:盡管列表允許把自身作為元素包含在內(nèi)总处,但建議要特別小心:在這樣的列表上,equals 和 hashCode 方法不再是定義良好的睛蛛。
某些列表實(shí)現(xiàn)對(duì)列表可能包含的元素有限制鹦马。例如,某些實(shí)現(xiàn)禁止 null 元素忆肾,而某些實(shí)現(xiàn)則對(duì)元素的類型有限制荸频。試圖添加不合格的元素會(huì)拋出未經(jīng)檢查的異常,通常是 NullPointerException 或 ClassCastException客冈。試圖查詢不合格的元素是否存在可能會(huì)拋出異常旭从,也可能簡(jiǎn)單地返回 false;某些實(shí)現(xiàn)會(huì)采用前一種行為场仲,而某些則采用后者和悦。概括地說,試圖對(duì)不合格元素執(zhí)行操作時(shí)渠缕,如果完成該操作后不會(huì)導(dǎo)致在列表中插入不合格的元素鸽素,則該操作可能拋出一個(gè)異常,也可能成功亦鳞,這取決于實(shí)現(xiàn)的選擇馍忽。此接口的規(guī)范中將這樣的異常標(biāo)記為“可選”。
面向位置的操作包括插入某個(gè)元素或 Collection 的功能燕差,還包括獲取遭笋、除去或更改元素的功能。在 List 中搜索元素可以從列表的頭部或尾部開始徒探,如果找到元素坐梯,還將報(bào)告元素所在的位置。
void add(int index, Object element)
boolean addAll(int index, Collection collection)
Object get(int index)
int indexOf(Object element)
int lastIndexOf(Object element)
Object remove(int index)
Object set(int index, Object element)
List 接口不但以位置友好的方式遍歷整個(gè)列表刹帕,還能處理集合的子集:
ListIterator listIterator()
ListIterator listIterator(int startIndex)
List subList(int fromIndex, int toIndex)
處理 subList() 時(shí)吵血,位于 fromIndex 的元素在子列表中谎替,而位于 toIndex 的元素則不是,提醒這一點(diǎn)很重要蹋辅。以下 for-loop 測(cè)試案例大致反映了這一點(diǎn):
for (int i=fromIndex; i<toIndex; i++) {
? // process element at position i
}
此外钱贯,我們還應(yīng)該提醒的是 ― 對(duì)子列表的更改(如 add()、remove() 和 set() 調(diào)用)對(duì)底層 List 也有影響侦另。
boolean add(E o)
? ? ? ? ? 向列表的尾部追加指定的元素(可選操作)秩命。
void add(int index, E element)
? ? ? ? ? 在列表的指定位置插入指定元素(可選操作)。
boolean addAll(Collection<?
extends E> c)
? ? ? ? ? 追加指定
collection 中的所有元素到此列表的結(jié)尾褒傅,順序是指定 collection 的迭代器返回這些元素的順序(可選操作)弃锐。
boolean addAll(int index, Collection<?
extends E> c)
? ? ? ? ? 將指定
collection 中的所有元素都插入到列表中的指定位置(可選操作)。
void clear()
? ? ? ? ? 從列表中移除所有元素(可選操作)殿托。
boolean contains(Object o)
? ? ? ? ? 如果列表包含指定的元素霹菊,則返回 true。
boolean containsAll(Collection<?> c)
? ? ? ? ? 如果列表包含指定
collection 的所有元素支竹,則返回 true旋廷。
boolean equals(Object o)
? ? ? ? ? 比較指定的對(duì)象與列表是否相等。
E get(int index)
? ? ? ? ? 返回列表中指定位置的元素礼搁。
int hashCode()
? ? ? ? ? 返回列表的哈希碼值饶碘。
int indexOf(Object o)
? ? ? ? ? 返回列表中首次出現(xiàn)指定元素的索引,如果列表不包含此元素馒吴,則返回
-1扎运。
boolean isEmpty()
? ? ? ? ? 如果列表不包含元素,則返回 true饮戳。
Iterator<E> iterator()
? ? ? ? ? 返回以正確順序在列表的元素上進(jìn)行迭代的迭代器绪囱。
int lastIndexOf(Object o)
? ? ? ? ? 返回列表中最后出現(xiàn)指定元素的索引,如果列表不包含此元素莹捡,則返回
-1鬼吵。
ListIterator<E> listIterator()
? ? ? ? ? 返回列表中元素的列表迭代器(以正確的順序)。
ListIterator<E> listIterator(int index)
? ? ? ? ? 返回列表中元素的列表迭代器(以正確的順序)篮赢,從列表的指定位置開始齿椅。
E remove(int index)
? ? ? ? ? 移除列表中指定位置的元素(可選操作)。
boolean remove(Object o)
? ? ? ? ? 移除列表中出現(xiàn)的首個(gè)指定元素(可選操作)启泣。
boolean removeAll(Collection<?> c)
? ? ? ? ? 從列表中移除指定
collection 中包含的所有元素(可選操作)涣脚。
boolean retainAll(Collection<?> c)
? ? ? ? ? 僅在列表中保留指定
collection 中所包含的元素(可選操作)。
E set(int index, E element)
? ? ? ? ? 用指定元素替換列表中指定位置的元素(可選操作)寥茫。
int size()
? ? ? ? ? 返回列表中的元素?cái)?shù)遣蚀。
List<E> subList(int fromIndex,
int toIndex)
? ? ? ? ? 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之間的部分視圖。
Object[] toArray()
? ? ? ? ? 返回以正確順序包含列表中的所有元素的數(shù)組。
<T>
T[]
toArray(T[] a)
? ? ? ? ? 返回以正確順序包含列表中所有元素的數(shù)組芭梯;返回?cái)?shù)組的運(yùn)行時(shí)類型是指定數(shù)組的運(yùn)行時(shí)類型险耀。
其中set方法返回的是被替換的內(nèi)容。
Linked 改快讀慢
Array 讀快改慢
Hash 兩都之間
Collection是集合接口
? ? |————Set子接口:無序玖喘,不允許重復(fù)甩牺。
? ? |————List子接口:有序,可以有重復(fù)元素累奈。
? ? 區(qū)別:Collections是集合類
? ? Set和List對(duì)比:
? ? Set:檢索元素效率低下贬派,刪除和插入效率高,插入和刪除不會(huì)引起元素位置改變澎媒。
? ? List:和數(shù)組類似搞乏,List可以動(dòng)態(tài)增長(zhǎng),查找元素效率高戒努,插入刪除元素效率低请敦,因?yàn)闀?huì)引起其他元素位置改變。
? ? Set和List具體子類:
? ? Set
? ? |————HashSet:以哈希表的形式存放元素柏卤,插入刪除速度很快冬三。
? ? List
? ? |————ArrayList:動(dòng)態(tài)數(shù)組
? ? |————LinkedList:鏈表匀油、隊(duì)列缘缚、堆棧。
? ? Array和java.util.Vector
? ? Vector是一種老的動(dòng)態(tài)數(shù)組敌蚜,是線程同步的桥滨,效率很低,一般不贊成使用弛车。
Map 接口
Map 接口不是 Collection 接口的繼承齐媒。而是從自己的用于維護(hù)鍵-值關(guān)聯(lián)的接口層次結(jié)構(gòu)入手。按定義纷跛,該接口描述了從不重復(fù)的鍵到值的映射喻括。
我們可以把這個(gè)接口方法分成三組操作:改變、查詢和提供可選視圖贫奠。
改變操作允許您從映射中添加和除去鍵-值對(duì)唬血。鍵和值都可以為 null。但是唤崭,您不能把Map 作為一個(gè)鍵或值添加給自身拷恨。
Object put(Object key, Object value)返回值是被替換的值。
Object remove(Object key)
void putAll(Map mapping)
void clear()
查詢操作允許您檢查映射內(nèi)容:
Object get(Object key)
boolean containsKey(Object key)
boolean containsValue(Object value)
int size()
boolean isEmpty()
最后一組方法允許您把鍵或值的組作為集合來處理谢肾。
public Set keySet()
public Collection values()
public Set entrySet()
因?yàn)橛成渲墟I的集合必須是唯一的腕侄,您用 Set 支持。因?yàn)橛成渲兄档募峡赡懿晃ㄒ唬肅ollection 支持冕杠。最后一個(gè)方法返回一個(gè)實(shí)現(xiàn) Map.Entry 接口的元素 Set微姊。
Map.Entry 接口
Map 的 entrySet() 方法返回一個(gè)實(shí)現(xiàn)Map.Entry 接口的對(duì)象集合。集合中每個(gè)對(duì)象都是底層 Map 中一個(gè)特定的鍵-值對(duì)拌汇。
通過這個(gè)集合迭代柒桑,您可以獲得每一條目的鍵或值并對(duì)值進(jìn)行更改。但是噪舀,如果底層 Map 在Map.Entry 接口的setValue() 方法外部被修改魁淳,此條目集就會(huì)變得無效,并導(dǎo)致迭代器行為未定義与倡。
HashMap 類和 TreeMap 類
“集合框架”提供兩種常規(guī)的 Map 實(shí)現(xiàn):HashMap 和TreeMap界逛。和所有的具體實(shí)現(xiàn)一樣,使用哪種實(shí)現(xiàn)取決于您的特定需要纺座。在Map 中插入息拜、刪除和定位元素,HashMap 是最好的選擇净响。但如果您要按順序遍歷鍵少欺,那么TreeMap 會(huì)更好。根據(jù)集合大小馋贤,先把元素添加到 HashMap赞别,再把這種映射轉(zhuǎn)換成一個(gè)用于有序鍵遍歷的 TreeMap 可能更快。使用HashMap 要求添加的鍵類明確定義了 hashCode() 實(shí)現(xiàn)配乓。有了TreeMap 實(shí)現(xiàn)仿滔,添加到映射的元素一定是可排序的。我們將在排序中詳細(xì)介紹犹芹。
為了優(yōu)化 HashMap 空間的使用崎页,您可以調(diào)優(yōu)初始容量和負(fù)載因子。這個(gè)TreeMap 沒有調(diào)優(yōu)選項(xiàng)腰埂,因?yàn)樵摌淇偺幱谄胶鉅顟B(tài)飒焦。
HashMap 和 TreeMap 都實(shí)現(xiàn)Cloneable 接口。
Hashtable 類和 Properties 類是Map 接口的歷史實(shí)現(xiàn)屿笼。我們將在Dictionary 類牺荠、Hashtable 類和 Properties 類中討論。
映射的使用示例
以下程序演示了具體 Map 類的使用刁卜。該程序?qū)ψ悦钚袀鬟f的詞進(jìn)行頻率計(jì)數(shù)志电。HashMap 起初用于數(shù)據(jù)存儲(chǔ)。后來蛔趴,映射被轉(zhuǎn)換為TreeMap 以顯示有序的鍵列列表挑辆。
import java.util.*;
public class MapExample {
? public static void main(String args[]) {
? ? Map map = new HashMap();
? ? Integer ONE = new Integer(1);
? ? for (int i=0, n=args.length; i<n; i++) {
? ? ? String key = args[i];
? ? ? Integer frequency = (Integer)map.get(key);
? ? ? if (frequency == null) {
? ? ? ? frequency = ONE;
? ? ? } else {
? ? ? ? int value = frequency.intValue();
? ? ? ? frequency = new Integer(value + 1);
? ? ? }
? ? ? map.put(key, frequency);
? ? }
? ? System.out.println(map);
? ? Map sortedMap = new TreeMap(map);
? ? System.out.println(sortedMap);
? }
}
用 Bill of Rights 的第三篇文章的文本運(yùn)行程序產(chǎn)生下列輸出,請(qǐng)注意有序輸出看起來多么有用!
無序輸出:
{prescribed=1, a=1, time=2, any=1, no=1, shall=1, nor=1, peace=1, owner=1, soldier=1, to=1, the=2, law=1, but=1, manner=1, without=1, house=1, in=4, by=1, consent=1, war=1, quartered=1, be=2, of=3}
有序輸出:
{a=1, any=1, be=2, but=1, by=1, consent=1, house=1, in=4, law=1, manner=1, no=1, nor=1, of=3, owner=1, peace=1, prescribed=1, quartered=1, shall=1, soldier=1, the=2, time=2, to=1, war=1, without=1}
Java集合框架是最常被問到的Java面試問題鱼蝉,要理解Java技術(shù)強(qiáng)大特性就有必要掌握集合框架洒嗤。這里有一些實(shí)用問題,常在核心Java面試中問到魁亦。
1渔隶、什么是Java集合API
Java集合框架API是用來表示和操作集合的統(tǒng)一框架,它包含接口洁奈、實(shí)現(xiàn)類间唉、以及幫助程序員完成一些編程的算法。簡(jiǎn)言之利术,API在上層完成以下幾件事:
編程更加省力呈野,提高城程序速度和代碼質(zhì)量
非關(guān)聯(lián)的API提高互操作性
節(jié)省學(xué)習(xí)使用新API成本
節(jié)省設(shè)計(jì)新API的時(shí)間
鼓勵(lì)、促進(jìn)軟件重用
具體來說印叁,有6個(gè)集合接口被冒,最基本的是Collection接口,由三個(gè)接口Set轮蜕、List昨悼、SortedSet繼承,另外兩個(gè)接口是Map跃洛、SortedMap率触,這兩個(gè)接口不繼承Collection,表示映射而不是真正的集合税课。
2闲延、什么是Iterator
一些集合類提供了內(nèi)容遍歷的功能痊剖,通過java.util.Iterator接口韩玩。這些接口允許遍歷對(duì)象的集合。依次操作每個(gè)元素對(duì)象陆馁。當(dāng)使用 Iterators時(shí)找颓,在獲得Iterator的時(shí)候包含一個(gè)集合快照。通常在遍歷一個(gè)Iterator的時(shí)候不建議修改集合本省叮贩。
3击狮、Iterator與ListIterator有什么區(qū)別?
Iterator:只能正向遍歷集合益老,適用于獲取移除元素彪蓬。ListIerator:繼承Iterator,可以雙向列表的遍歷捺萌,同樣支持元素的修改档冬。
4、什么是HaspMap和Map?
Map是接口酷誓,Java 集合框架中一部分披坏,用于存儲(chǔ)鍵值對(duì),HashMap是用哈希算法實(shí)現(xiàn)Map的類盐数。
5棒拂、HashMap與HashTable有什么區(qū)別?對(duì)比Hashtable VS HashMap
兩者都是用key-value方式獲取數(shù)據(jù)玫氢。Hashtable是原始集合類之一(也稱作遺留類)帚屉。HashMap作為新集合框架的一部分在Java2的1.2版本中加入。它們之間有一下區(qū)別:
HashMap和Hashtable大致是等同的漾峡,除了非同步和空值(HashMap允許null值作為key和value涮阔,而Hashtable不可以)。
HashMap沒法保證映射的順序一直不變灰殴,但是作為HashMap的子類LinkedHashMap敬特,如果想要預(yù)知的順序迭代(默認(rèn)按照插入順序),你可以很輕易的置換為HashMap牺陶,如果使用Hashtable就沒那么容易了伟阔。
HashMap不是同步的,而Hashtable是同步的掰伸。
迭代HashMap采用快速失敗機(jī)制皱炉,而Hashtable不是,所以這是設(shè)計(jì)的考慮點(diǎn)狮鸭。
6合搅、在Hashtable上下文中同步是什么意思?
同步意味著在一個(gè)時(shí)間點(diǎn)只能有一個(gè)線程可以修改哈希表歧蕉,任何線程在執(zhí)行hashtable的更新操作前需要獲取對(duì)象鎖灾部,其他線程等待鎖的釋放。
7惯退、什么叫做快速失敗特性
從高級(jí)別層次來說快速失敗是一個(gè)系統(tǒng)或軟件對(duì)于其故障做出的響應(yīng)赌髓。一個(gè)快速失敗系統(tǒng)設(shè)計(jì)用來即時(shí)報(bào)告可能會(huì)導(dǎo)致失敗的任何故障情況,它通常用來停止正常的操作而不是嘗試?yán)^續(xù)做可能有缺陷的工作催跪。當(dāng)有問題發(fā)生時(shí)锁蠕,快速失敗系統(tǒng)即時(shí)可見地發(fā)錯(cuò)錯(cuò)誤告警。在Java中懊蒸,快速失敗與iterators有關(guān)荣倾。如果一個(gè)iterator在集合對(duì)象上創(chuàng)建了,其它線程欲“結(jié)構(gòu)化”的修改該集合對(duì)象骑丸,并發(fā)修改異常 (ConcurrentModificationException) 拋出舌仍。
8鳖孤、怎樣使Hashmap同步?
HashMap可以通過Map m = Collections.synchronizedMap(hashMap)來達(dá)到同步的效果抡笼。
9苏揣、什么時(shí)候使用Hashtable,什么時(shí)候使用HashMap
基本的不同點(diǎn)是Hashtable同步HashMap不是的推姻,所以無論什么時(shí)候有多個(gè)線程訪問相同實(shí)例的可能時(shí)平匈,就應(yīng)該使用Hashtable,反之使用HashMap藏古。非線程安全的數(shù)據(jù)結(jié)構(gòu)能帶來更好的性能增炭。
如果在將來有一種可能—你需要按順序獲得鍵值對(duì)的方案時(shí),HashMap是一個(gè)很好的選擇拧晕,因?yàn)橛蠬ashMap的一個(gè)子類 LinkedHashMap隙姿。所以如果你想可預(yù)測(cè)的按順序迭代(默認(rèn)按插入的順序),你可以很方便用LinkedHashMap替換HashMap厂捞。反觀要是使用的Hashtable就沒那么簡(jiǎn)單了输玷。同時(shí)如果有多個(gè)線程訪問HashMap,Collections.synchronizedMap()可以代替靡馁,總的來說HashMap更靈活欲鹏。
10、為什么Vector類認(rèn)為是廢棄的或者是非官方地不推薦使用臭墨?或者說為什么我們應(yīng)該一直使用ArrayList而不是Vector
你應(yīng)該使用ArrayList而不是Vector是因?yàn)槟J(rèn)情況下你是非同步訪問的赔嚎,Vector同步了每個(gè)方法,你幾乎從不要那樣做胧弛,通常有想要同步的是整個(gè)操作序列尤误。同步單個(gè)的操作也不安全(如果你迭代一個(gè)Vector,你還是要加鎖结缚,以避免其它線程在同一時(shí)刻改變集合).而且效率更慢损晤。當(dāng)然同樣有鎖的開銷即使你不需要,這是個(gè)很糟糕的方法在默認(rèn)情況下同步訪問掺冠。你可以一直使用Collections.sychronizedList來裝飾一個(gè)集合沉馆。
事實(shí)上Vector結(jié)合了“可變數(shù)組”的集合和同步每個(gè)操作的實(shí)現(xiàn)码党。這是另外一個(gè)設(shè)計(jì)上的缺陷德崭。Vector還有些遺留的方法在枚舉和元素獲取的方法,這些方法不同于List接口揖盘,如果這些方法在代碼中程序員更趨向于想用它眉厨。盡管枚舉速度更快,但是他們不能檢查如果集合在迭代的時(shí)候修改了兽狭,這樣將導(dǎo)致問題憾股。盡管以上諸多原因鹿蜀,oracle也從沒宣稱過要廢棄Vector。