從圖1中可以看到,,Collection是集合繼承樹中最頂層的接口,,幾乎所有的Java集合框架成員都繼承實(shí)現(xiàn)了Collection接口,或者與其有密切關(guān)系,。Collection提供了關(guān)于集合的通用操作,。Set接口和List接口都繼承了Collection接口,而Map接口沒有繼承Collection接口,。因此,,Set對象和List對象都可以調(diào)用Collection接口的方法,而Map對象則不可以,。 下面我們對這三種類型接口的結(jié)構(gòu)加以說明:Set有點(diǎn)類似數(shù)學(xué)中集合的定義,,是無序的、沒有重復(fù)項(xiàng)目的集合,。List是位置性集合,,加進(jìn)清單的元素可以加在清單中特定位置或加到末尾,可以保存重復(fù)的元素,。Map用于關(guān)鍵字/數(shù)值對,,其中關(guān)鍵字是數(shù)值的惟一標(biāo)識(不可重復(fù)),用戶可以按關(guān)鍵字存取數(shù)據(jù),,數(shù)據(jù)可重復(fù),。具體形式如圖2所示: 圖2 各集合元素存放示例 (1)Collection:集合層次中的根接口,JDK 沒有提供這個接口直接的實(shí)現(xiàn)類,。 (2)Set:不能包含重復(fù)的元素,。 (3) List:是一個有序的集合,可以包含重復(fù)的元素。提供了按索引訪問的方式,。 (4)Map:包含了 key-value 對,。Map 不能包含重復(fù)的 key。 三,、List用法總結(jié)3.1 List接口List的主要特征使其元素已先行方式存儲,,集合中允許存放重復(fù)對象。List接口主要的實(shí)現(xiàn)類包括: (1)ArrayList:代表長度可變的數(shù)組,。允許對元素進(jìn)行快速的隨機(jī)訪問,,但是向ArrayList中插入與刪除元素的速度較慢。 (2)LinkedList :在實(shí)現(xiàn)中采用鏈表數(shù)據(jù)結(jié)構(gòu),,元素之間是雙鏈接,。對順序訪問進(jìn)行了優(yōu)化,向List中插入和刪除元素的速度較快,,隨機(jī)訪問速度則相對較慢,,隨機(jī)訪問是指檢索位于特定索引位置元素,當(dāng)需要快速插入和刪除時LinkedList成為List中的不二選擇,。 (3)Vector :是ArrayList的線程安全版本,,性能比ArrayList要低,現(xiàn)在已經(jīng)很少使用,。 3.2 ArrayList用法3.2.1,、ArrayList是個集合 集合是可以往里面添東西的,用add(E e)方法往里面加(把E都看做Object) 例子:ArrayList類中的add和get方法(add方法向集合中添加數(shù)據(jù),,get方法將集合中指定下標(biāo)位置的數(shù)據(jù)取出) (1)size()方法,,返回集合中的元素個數(shù),類似于數(shù)組中的length屬性 (2)clear()方法,,將集合中的所有元素都給清除 (3)isEmpty()方法判斷集合是否為空,,為空返回true (4)remove(int index)方法是刪除集合中指定位置的元素,清除的原理是你清除了第一個后,,后面的元素往前移,,第一個變第0個了,原來第三個元素就沒啦 (5)remove(Object ob)是remove的重載,,一個是根據(jù)索引來刪除,,一個是根據(jù)具體對象來刪除,比如remove('Hello'); (6)indexOf(Obejct ob)判斷某個元素在索引的第幾個位置上,。 在數(shù)組中查看數(shù)組元素個數(shù),,用數(shù)組的length屬性,在集合中查看集合元素個數(shù),,用集合的size()方法,。 3.2.2、ArrayList使用范例 import java.awt.List;
import java.util.ArrayList;
import java.util.Iterator;
/**
* @author 林炳文
* @time 2015/2/5
* ArrayList用法示例說明
*
*/
public class Main {
public static void main(String[] args) {
//ArrayList用法示例
ArrayList<String> m_ArrayList=new ArrayList<String>();
m_ArrayList.add('Evankaka');
m_ArrayList.add('林炳文');
m_ArrayList.add('德德');
m_ArrayList.add('Evankaka');
m_ArrayList.add('小紅');
m_ArrayList.set(2,'文炳林');// 將索引位置為2的對象修改
m_ArrayList.add(3,'秀秀');// 將對象添加到索引位置為3的位置
//ArrayList遍歷方法1
Iterator<String> it_ArrayList = m_ArrayList.iterator();
System.out.println('ArrayList遍歷方法1');
while (it_ArrayList.hasNext()) {
System.out.println(it_ArrayList.next());
}
//ArrayList遍歷方法2
System.out.println('ArrayList遍歷方法2');
for(Object o:m_ArrayList){
System.out.println(o);
}
//ArrayList遍歷方法2
System.out.println('ArrayList遍歷方法3');
for(int i = 0; i<m_ArrayList.size(); i ){
System.out.println(m_ArrayList.get(i));
}
//刪除元素
m_ArrayList.remove('Evankaka');
it_ArrayList = m_ArrayList.iterator();
System.out.println('ArrayList刪除元素后的遍歷');
while (it_ArrayList.hasNext()) {
String m_String=it_ArrayList.next();
if(m_String.equals('秀秀')){
it_ArrayList.remove();
}else{
System.out.println(m_String);
}
}
}
} 輸出結(jié)果: ArrayList遍歷方法1 3.2.3,、ArrayList注意 (1)使用Iterator迭代集合過程中,,不可修改集合元素,否則會引發(fā)異常,。并且Iterator只能向后迭代 (2)如果你想在循環(huán)過程中去掉某個元素,只能調(diào)用it.remove方法, 不能使用list.remove方法, 否則一定出并發(fā)訪問的錯誤. 3.3 LinkedList用法LinkedList類是鏈表節(jié)點(diǎn)各種操作的實(shí)現(xiàn),,LinkedList類實(shí)現(xiàn)了一個帶有頭尾引用的通用型雙向鏈表。注意,,此實(shí)現(xiàn)不是同步的,。如果多個線程同時訪問列表,而其中至少一個線程從結(jié)構(gòu)上修改了該列表,,則它必須保持外部同步,。(結(jié)構(gòu)修改指添加或刪除一個或多個元素的任何操作;僅設(shè)置元素的值不是結(jié)構(gòu)修改,。)這一般通過對自然封裝該列表的對象進(jìn)行同步操作來完成,。如果不存在這樣的對象,則應(yīng)該使用 Collections.synchronizedList 方法來“包裝”該列表,。最好在創(chuàng)建時完成這一操作,,以防止對列表進(jìn)行意外的不同步訪問。 四,、set接口set集合中多個對象之間沒有明顯的順序,,set與Collection的結(jié)構(gòu)基本上完全一樣,不同在于set不能包含重復(fù)元素,。Set判斷兩個對象相同不是使用==運(yùn)算符,,而是根據(jù)equals方法。也就是說主要兩個對象用equals方法比較返回true,,Set就不會接受這兩個對象,。 HashSet是Set接口的典型實(shí)現(xiàn),大多數(shù)時候使用Set集合就是使用這個類,。 4.1 HashSet說明與范例 HashSet按hash算法來存儲集合中的元素,,因此具有很好的存儲和查找性能。 使用范例: package com.collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
public class Main
{
public static void main(String [] args)
{
HashSet h=new HashSet();
h.add('1st');
h.add('2nd');
h.add(new Integer(3));
h.add(new Double(4.0));
h.add('2nd'); //重復(fù)元素,,未被添加
h.add(new Integer(3)); //重復(fù)元素,未被添加
h.add(new Date());
System.out.println('開始:size=' h.size());
Iterator it=h.iterator();
while(it.hasNext())
{
Object o=it.next();
System.out.println(o);
}
h.remove('2nd');
System.out.println('移除元素后:size=' h.size());
System.out.println(h);
}
} 結(jié)果:開始:size=5 4.2 TreeSet TreeSet描述的是Set的一種變體——可以實(shí)現(xiàn)排序等功能的集合,,它在將對象元素添加到集合中時會自動按照某種比較規(guī)則將其插入到有序的對象序列中,,并保證該集合元素組成時刻按照“升序”排列。 使用范例: package com.collection;
import java.util.TreeSet;
import java.util.Iterator;
public class Main
{
public static void main(String [] args)
{
TreeSet ts=new TreeSet();
ts.add('orange');
ts.add('apple');
ts.add('banana');
ts.add('grape');
Iterator it=ts.iterator();
while(it.hasNext())
{
String fruit=(String)it.next();
System.out.println(fruit);
}
}
} 結(jié)果: apple 4.3 Set總結(jié)(1) HashSet和TreeSet是Set的兩個典型實(shí)現(xiàn),。HashSet的性能總是比TreeSet好(特別是常用的添加,、查詢等操作),因?yàn)門reeSet需要額外的紅黑樹算法來維護(hù)集合元素的次序,。只有當(dāng)需要一個保存排序的Set時,,才應(yīng)該使用TreeSet,否則都應(yīng)該使用HashSet,。(2) LinkedHashSet是HashSet的子類,,該集合也是根據(jù)元素hashCode值來決定元素存儲位置,但它同時使用鏈表維護(hù)元素的次序,,這樣使得元素看起來是以插入的順序保存的,。LinkedHashSet需要維護(hù)元素的插入順序,因此性能略低于HashSet的性能,,但在迭代訪問Set里的全部元素時將有很好的性能,,又因?yàn)殒湵淼拇嬖冢闅vLinkedHashSet會更快,。 (3)TreeSet是SortedSet接口的實(shí)現(xiàn),,TreeSet可以確保集合元素處于排序狀態(tài),TreeSet并不是根據(jù)元素的插入順序進(jìn)行排序,,而是根據(jù)元素的實(shí)際值來進(jìn)行排序的,。 (4)EnumSet是所有Set實(shí)現(xiàn)類中性能最好的,但它只能保存同一個枚舉類的枚舉值作為集合元素,。 (5)必須指出的是Set的三個實(shí)現(xiàn)類HashSet,、TreeSet和EnumSet都是線程不安全的,如果有多條線程同時訪問一個Set集合,,并有超過一條線程修改了該Set集合,,則必須手動保證該Set集合的同步性。通??梢酝ㄟ^Collections工具類的synchronizedSortedSet方法來包裝該Set集合,。此操作最好在創(chuàng)建時進(jìn)行。 五 Map接口 將鍵映射到值的對象,。一個映射不能包含重復(fù)的鍵,;每個鍵最多只能映射到一個值,。此接口取代 Dictionary 類,后者完全是一個抽象類,,而不是一個接口,。
Map 提供了一個更通用的元素存儲方法。Map 集合類用于存儲元素對(稱作“鍵”和“值”),,其中每個鍵映射到一個值,。從概念上而言,您可以將 List 看作是具有數(shù)值鍵的 Map,。而實(shí)際上,,除了 List 和 Map 都在定義 java.util 中外,兩者并沒有直接的聯(lián)系,。本文將著重介紹核心 Java 發(fā)行套件中附帶的 Map,,同時還將介紹如何采用或?qū)崿F(xiàn)更適用于您應(yīng)用程序特定數(shù)據(jù)的專用 Map。 5.1,、了解 Map 接口和方法 Java 核心類中有很多預(yù)定義的 Map 類,。在介紹具體實(shí)現(xiàn)之前,,我們先介紹一下 Map 接口本身,以便了解所有實(shí)現(xiàn)的共同點(diǎn),。Map 接口定義了四種類型的方法,,每個 Map 都包含這些方法。下面,,我們從兩個普通的方法開始對這些方法加以介紹,。 表 1:覆蓋的方法。我們將這 Object 的這兩個方法覆蓋,,以正確比較 Map 對象的等價性,。
5.2、Map 構(gòu)建 Map 定義了幾個用于插入和刪除元素的變換方法,。 表 2:Map 更新方法: 可以更改 Map 內(nèi)容,。
盡管您可能注意到,,縱然假設(shè)忽略構(gòu)建一個需要傳遞給 putAll() 的 Map 的開銷,,使用 putAll() 通常也并不比使用大量的 put() 調(diào)用更有效率,但 putAll() 的存在一點(diǎn)也不稀奇,。這是因?yàn)?,putAll() 除了迭代 put() 所執(zhí)行的將每個鍵值對添加到 Map 的算法以外,還需要迭代所傳遞的 Map 的元素,。但應(yīng)注意,,putAll() 在添加所有元素之前可以正確調(diào)整 Map 的大小,因此如果您未親自調(diào)整 Map 的大?。ㄎ覀儗Υ诉M(jìn)行簡單介紹),,則 putAll() 可能比預(yù)期的更有效。 5.3,、查看 Map 迭代 Map 中的元素不存在直接了當(dāng)?shù)姆椒?。如果要查詢某個 Map 以了解其哪些元素滿足特定查詢,或如果要迭代其所有元素(無論原因如何),,則您首先需要獲取該 Map 的“視圖”,。有三種可能的視圖。
前兩個視圖均返回 Set 對象,,第三個視圖返回 Collection 對象,。就這兩種情況而言,問題到這里并沒有結(jié)束,,這是因?yàn)槟鸁o法直接迭代 Collection 對象或 Set 對象,。要進(jìn)行迭代,您必須獲得一個 Iterator 對象,。因此,,要迭代 Map 的元素,,必須進(jìn)行比較煩瑣的編碼
Iterator keyValuePairs = aMap.entrySet().iterator();
Iterator keys = aMap.keySet().iterator();
Iterator values = aMap.values().iterator();
值得注意的是,這些對象(Set,、Collection 和 Iterator)實(shí)際上是基礎(chǔ) Map 的視圖,,而不是包含所有元素的副本。這使它們的使用效率很高,。另一方面,,Collection 或 Set 對象的 toArray() 方法卻創(chuàng)建包含 Map 所有元素的數(shù)組對象,因此除了確實(shí)需要使用數(shù)組中元素的情形外,,其效率并不高,。 5.4、遍歷mappackage com.test;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class Test {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put('first', 'linlin');
map.put('second', 'bingbing');
map.put('third', 'wenwen');
map.put('first', 'linlin2');
// 第一種:通過Map.keySet遍歷key和value
System.out.println('===================通過Map.keySet遍歷key和value:===================');
for (String key : map.keySet()) {
System.out.println('key= ' key ' and value= ' map.get(key));
}
// 第二種:通過Map.entrySet使用iterator遍歷key和value
System.out.println('===================通過Map.entrySet使用iterator遍歷key和value:===================');
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
System.out.println('key= ' entry.getKey() ' and value= '
entry.getValue());
}
// 第三種:通過Map.entrySet遍歷key和value
System.out.println('===================通過Map.entrySet遍歷key和value:===================');
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println('key= ' entry.getKey() ' and value= '
entry.getValue());
}
// 第四種:通過Map.values()遍歷所有的value,,但是不能遍歷鍵key
System.out.println('===================通過Map.values()遍歷所有的value:===================');
for (String v : map.values()) {
System.out.println('value= ' v);
}
}
}
輸出結(jié)果如下 |
|