常見Java面試題和答案_第1頁
常見Java面試題和答案_第2頁
常見Java面試題和答案_第3頁
常見Java面試題和答案_第4頁
常見Java面試題和答案_第5頁
已閱讀5頁,還剩131頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

Interface與AbstractClass的區(qū)別

在Java語言中,abstractclass和interface是支持抽象類定義的兩種機制。

正是由于這兩種機制的存在,才賦予了Java強大的面向對象能力。abstract

class和interface之間在對于抽象類定義的支持方面具有很大的相似性,甚至

可以相互替換,因此很多開發(fā)者在進行抽象類定義時對于abstractclass和

interface的選擇顯得比較隨意。其實,兩者之間還是有很大的區(qū)別的,對于它

們的選擇甚至反映出對于問題領域本質的理解、對于設計意圖的理解是否正確、

合理。

AbstractclassInterface

實例

不能不能

i種繼承關系,一個類只能使用

類一次繼承關系??梢酝ㄟ^繼承多一>個類可以實現(xiàn)多個interface

個接口實現(xiàn)多重繼承

數(shù)據(jù)靜態(tài)的不能被修改即必須是static

可有自己的

成員final,一般不在此定義

可以私有的,非abstract方法,不可有私有的,默認是public,abstract

方法

必須實現(xiàn)類型

可有私有的,默認是friendly不可有私有的,默認是publicstatic

變量型,其值可以在子類中重新定義,final型,且必須給其初值,實現(xiàn)類中不

也可以重新賦值能重新定義,不能改變其值。

設計

表示的是“is-a”關系表示的是“l(fā)ike-a”關系

理念

實現(xiàn)需要繼承,要用extends要用implements

abstractclass和interface在Java語言中都是用來進行抽象類(本文中的抽

象類并非從abstractclass翻譯而來,它表示的是一個抽象體,而abstract

class為Java語言中用于定義抽象類的一種方法)定義的,那么什么是抽象類,

使用抽象類能為我們帶來什么好處呢?

聲明方法的存在而不去實現(xiàn)它的類被叫做抽象類(abstractclass),它用于要

創(chuàng)建一個體現(xiàn)某些基本行為的類,并為該類聲明方法,但不能在該類中實現(xiàn)該類

的情況。不能創(chuàng)建abstract類的實例。然而可以創(chuàng)建一個變量,其類型是一個

抽象類,并讓它指向具體子類的一個實例。不能有抽象構造函數(shù)或抽象靜態(tài)方法。

Abstract類的子類為它們父類中的所有抽象方法提供實現(xiàn),否則它們也是抽象

類為。取而代之,在子類中實現(xiàn)該方法。知道其行為的其它類可以在類中實現(xiàn)這

些方法。

接口(interface)是抽象類的變體。在接口中,所有方法都是抽象的。多繼承

性可通過實現(xiàn)這樣的接口而獲得。接口中的所有方法都是抽象的,沒有一個有程

序體。接口只可以定義staticfinal成員變量。接口的實現(xiàn)與子類相似,除了

該實現(xiàn)類不能從接口定義中繼承行為。當類實現(xiàn)特殊接口時,它定義(即將程序

體給予)所有這種接口的方法。然后,它可以在實現(xiàn)了該接口的類的任何對象上

調(diào)用接口的方法。由于有抽象類,它允許使用接口名作為引用變量的類型。通常

的動態(tài)聯(lián)編將生效。引用可以轉換到接口類型或從接口類型轉換,instanceof運

算符可以用來決定某對象的類是否實現(xiàn)了接口。

接口可以繼承接口。抽象類可以實現(xiàn)(implements)接口,抽象類是可以繼承實體

類,但前提是實體類必須有明確的構造函數(shù)。接口更關注“能實現(xiàn)什么功能”,

而不管“怎么實現(xiàn)的”。

1.相同點

A.兩者都是抽象類,都不能實例化。

B.interface實現(xiàn)類及abstrctclass的子類都必須要實現(xiàn)已經(jīng)聲明的抽象

方法。

2.不同點

A.interface需要實現(xiàn),要用implements,而abstractclass需要繼承,要

用extendso

B.一個類可以實現(xiàn)多個interface,但一個類只能繼承一個abstractclass。

C.interface強調(diào)特定功能的實現(xiàn),而abstractclass強調(diào)所屬關系。

D.盡管interface實現(xiàn)類及abstrctclass的子類都必須要實現(xiàn)相應的抽象

方法,但實現(xiàn)的形式不同。interface中的每一個方法都是抽象方法,都只是聲

明的(declaration,沒有方法體),實現(xiàn)類必須要實現(xiàn)。而abstractclass的子

類可以有選擇地實現(xiàn)。

這個選擇有兩點含義:

一是Abastractclass中并非所有的方法都是抽象的,只有那些冠有

abstract的方法才是抽象的,子類必須實現(xiàn)。那些沒有abstract的方法,在

Abstrctclass中必須定義方法體。

二是abstractclass的子類在繼承它時,對非抽象方法既可以直接繼承,

也可以覆蓋;而對抽象方法,可以選擇實現(xiàn),也可以通過再次聲明其方法為抽象

的方式,無需實現(xiàn),留給其子類來實現(xiàn),但此類必須也聲明為抽象類。既是抽象

類,當然也不能實例化。

E.abstractclass是interface與Class的中介。

interface是完全抽象的,只能聲明方法,而且只能聲明pulic的方法,不能

聲明private及protected的方法,不能定義方法體,也不能聲明實例變量。然

而,interface卻可以聲明常量變量,并且在JDK中不難找出這種例子。但將常

量變量放在interface中違背了其作為接口的作用而存在的宗旨,也混淆了

interface與類的不同價值。如果的確需要,可以將其放在相應的abstractclass

或Class中o

abstractclass在interface及Class中起到了承上啟下的作用。一方面,

abstractclass是抽象的,可一以聲明抽象方法,以規(guī)范子類必須實現(xiàn)的功能;

另一方面,它又可以定義缺省的方法體,供子類直接使用或覆蓋。另外,它還可

以定義自己的實例變量,以供子類通過繼承來使用。

3.interface的應用場合

A.類與類之前需要特定的接口進行協(xié)調(diào),而不在乎其如何實現(xiàn)。

B.作為能夠實現(xiàn)特定功能的標識存在,也可以是什么接口方法都沒有的純粹

標識。

C.需要將一組類視為單一的類,而調(diào)用者只通過接口來與這組類發(fā)生聯(lián)系。

D.需要實現(xiàn)特定的多項功能,而這些功能之間可能完全沒有任何聯(lián)系。

4.abstractclass的應用場合

一句話,在既需要統(tǒng)一的接口,又需要實例變量或缺省的方法的情況下,就可

以使用它。最常見的有:

A.定義了一組接口,但又不想強迫每個實現(xiàn)類都必須實現(xiàn)所有的接口??梢?/p>

用abstractclass定義一組方法體,甚至可以是空方法體,然后由子類選擇自

己所感興趣的方法來覆蓋。

B.某些場合下,只靠純粹的接口不能滿足類與類之間的協(xié)調(diào),還必需類中表

示狀態(tài)的變量來區(qū)別不同的關系。abstract的中介作用可以很好地滿足這一點。

C.規(guī)范了一組相互協(xié)調(diào)的方法,其中一些方法是共同的,與狀態(tài)無關的,可

以共享的,無需子類分別實現(xiàn);而另一些方法卻需要各個子類根據(jù)自己特定的狀

態(tài)來實現(xiàn)特定的功能。

Public,Private,Protected?default?

方法的訪問控制

訪問說

不同、、、即符publicprotecteddefaultprivate

情形下、'、、、

同類////

同包///

_______________S__

子類//

通用性/

==、equals的區(qū)別?

equals方法(是String類從它的超類Object中繼承的)被用來檢測兩個對象是否相等,即

兩個對象的內(nèi)容是否相等。

==用于比較引用和比較基本數(shù)據(jù)類型時具有不同的功能:

比較基本數(shù)據(jù)類型,如果兩個值相同,則結果為true

而在比較引用時,如果引用指向內(nèi)存中的同一對象,結果為true

Eg:sl=newString("sony");〃創(chuàng)建的是字符串對象

sl.equals("sony");〃返回

truesl=="sony"〃返回false

〃如果

si="sony";

si=="sony"〃返回true

常用的JAVA集合及異同

集合指多個元素的聚集體。JavaCollectionsFramework是Java提供的對集合進行

定義,操作,和管理的包含一組接口,類的體系結構。本文對JavaCollectionsFramework

的體系結構作一個全面深入的介紹。

Java集合框架的基本接口/類層次結構:

java.util.Collection[I]

+-java.util.List[I]

+一java.util.ArrayList[C]

+-java.util.LinkedList[C]

+一java.util.Vector[C]

+-java.util.Stack

+-java.util.Set[I]

+-java.util.HashSet[C]

+--java.util.SortedSet[I]

+-java.util.TreeSet[C]

java.util.Map

+-java.util.SortedMap[I]

+--java.util.TreeMap[C]

+-java.util.Hashtable[C]

+--java.util.HashMap[C]

+--java.util.LinkedHashMap[C]

+--java.util.WeakHashMap[C]

[I]:接口

[C]:類

Collection集合

Collection是最基本的集合接口,一個Collection代表一組Object的集合,這些Objcct

被稱作Collection的元素。

根據(jù)用途的不同,Collection又劃分為List與Set。

Collection接口的主要接口方法有:

viewplaincopytoclipboardprint?

publicinterfaceCollection

extendsIterable

〃取得Collection的容量(元素數(shù)目)

publicabstractintsize();

〃判斷是否為空

publicabstractbooleanisEmpty();

〃判斷是否包含某對象元素

publicabstractbooleancontains(Objectobj);

〃取得對所有元素的遍歷??梢酝ㄟ^Iterator提供的方法遍歷集合的元素

publicabstractIteratoriterator();

〃將集合元素以數(shù)據(jù)形式返回

publicabstractObject[]toArray();

publicabstractObject[]toArray(Objectaobj[]);

〃向集合體插入?個新的元素

publicabstractbooleanadd(Objectobj);

〃從集合體刪除一個元素

publicabstractbooleanremove(Objectobj);

〃是否包含所有collection里的所有元素

publicabstractbooleancontainsAII(Collectioncollection);

〃插入collection里的所有元素

publicabstractbooleanaddAII(Collectioncollection);

〃移除collection里的所有元素

publicabstractbooleanremoveAII(Collectioncollection);

publicabstractbooleanretainAII(Collectioncollection);

〃移除所有元素

publicabstractvoidclear();

//...othermethods

)

該接口定義了集合的基本操作方法。

List集合

List繼承自Collection接口。List是一種有序集合,List中的元素可以根據(jù)索引(順序

號:元素在集合中處于的位置信息)進行取得/刪除/插入操作。

跟Set集合不同的是,List允許有重復元素。對于滿足el.equals(e2)條件的el與e2對象

元素,可以同時存在于List集合中。當然,也有List的實現(xiàn)類不允許重復元素的存在.

同時,List還提供—t'listiterator()方法,返回一個Listiterator接口對象,和Iterator

接口相比,Listiterator添加元素的添加,刪除,和設定等方法,還能向前或向后遍歷。

List接口添加的主要方法有:

viewplaincopytoclipboardprint?

publicinterfaceList

extendsCollection

(

//...otherCollectionmethods

〃根據(jù)索引取得元素

publicabstractObjectget(inti);

〃在指定位置(索引)處插入新的元素

publicabstractObjectset(inti,Objectobj);

〃在List的尾部插入新的元素

publicabstractvoidadd(inti,Objectobj);

〃刪除指定位置(索引)處的元素

publicabstractObjectremove(inti);

〃取得指定對象的最開始的索引位置

publicabstractintindexOf(Objectobj);

〃取得指定對象的最后的索引位置

publicabstractintlastlndexOf(Objectobj);

//List提供的新的遍歷方法

publicabstractListiteratorlistlterator();

〃從指定位置i處開始迭代。最初next。方法返回的將是位置i處的元素。

publicabstractListiteratorlistlterator(inti);

〃取得從位置i到j的所有元素(包含i但不包含j位置的元素),返回一個新的集合對象。

publicabstractListsubList(inti,intj);

Set集合

Set繼承自Collection接口。Set是一種不能包含有重復元素的集合,即對于滿足

el.equals(e2)條件的el與e2對象元素,不能同時存在于同一個Set集合里,換句話說,

Set集合里任意兩個元素el和e2都滿足el.equals(e2)==false條件,Set最多有一-個null

元素。

因為Set的這個制約,在使用Set集合的時候,應該注意:

1,為Set集合里的元素的實現(xiàn)類實現(xiàn)一個有效的equals(Object)方法。

2,對Set的構造函數(shù),傳入的Collection參數(shù)不能包含重復的元素。

Set接口里定義的方法與Collection基本?樣,這里不再重述。

Map集合

Map沒有繼承Collection接口。也就是說Map和Collection是2種不同的集合。Collection

可以看作是(value)的集合,而Map可以看作是(key,value)的集合。

Map接口山Map的內(nèi)容提供3種類型的集合視圖,,組key集合,■■組value集合,或者?,

組key-value映射關系的集合

Map接口

viewplaincopytoclipboardprint?

publicinterfaceMap

(

//

publicstaticinterfaceEntry

(

publicabstractObjectgetKeyf);

publicabstractObjectgetValue();

publicabstractObjectsetValue(Objectobj);

〃…

)

〃作用基本等同Collection接口的方法

publicabstractintsize();

publicabstractbooleanisEmpty();

publicabstractbooleancontainsKey(Objectobj);

publicabstractbooleancontainsValue(Objectobj);

publicabstractObjectget(Objectobj);

publicabstractObjectput(Objectobj,Objectobjl);

publicabstractObjectremove(Objectobj);

publicabstractvoidclear();

〃添加map里包含的所有元素

publicabstractvoidputAII(Mapmap);

〃key集合

publicabstractSetkeySet();

//value集合

publicabstractCollectionvalues();

//key-value映射關系的集合Set<Entry>

publicabstractSetentrySet();

//...

集合的遍歷:

所有java.util.Collection的實現(xiàn)類必須實現(xiàn)

publicabstractIteratoriterator();

方法以支持對所包含的對象進行遍歷。

java.util.Iterator[I]

十一一java.util.Listiterator[I]

Iterator接口:

viewplaincopytoclipboardprint?

publicinterfaceIterator

(

〃判斷是否存在下一個元素

publicabstractbooleanhasNext();

〃返回下一個可用的元素

publicabstractObjectnext();

〃移除當前元素

publicabstractvoidremove();

Listiterator接口:

viewplaincopytoclipboardprint?

publicinterfaceListiterator

extendsIterator

(

//othermethodsdefinedinIterator

〃判斷是否存在上一個元素

publicabstractbooleanhasPrevious();

〃返回上一個可用的元素

publicabstractObjectprevious();

〃取得下一個可用元素的索引位置

publicabstractintnextlndex();

〃取得上一個可用元素的索引位置

publicabstractintpreviouslndex();

〃替換當前位置的元素

publicabstractvoidset(Objectobj);

〃在當前位置插入新元素

publicabstractvoidadd(Objectobj);

對集合操作的工具類

Java提供了java.util.Collections,以及java.util.Arrays類簡化對集合的操作

java.util.Collections主要提供一些static方法用來操作或創(chuàng)建Collection,Map等集

合。

java.util.Arrays主要提供static方法對數(shù)組進行操作。

ArrayList與LinkedList等的性能比較

JavaCollectionsFramework的List集合類主要有ArrayList,LinkedList,Vector,Stack

等。本文主要對它們作一個比較,說明它們的異同點以及性能上的區(qū)別等。

概要

我們在JavaCollectionsFramework-Java集合框架List,Map,Set等全面介紹之概要

篇一文中對Java集合框架(JavaCollectionsFramework)做了一個比較全面的介紹。

該文粗略地介紹了List集合的概念定義等。

List集合

List繼承自Collection接口。List是一種有序集合,List中的元素可以根據(jù)索引(順序

號:元素在集合中處于的位置信息)進行取得/刪除/插入操作。

跟Set集合不同的是,List允許有重復元素。對于滿足el.equals(e2)條件的el與e2對象

元素,可以同時存在于List集合中。當然,也有List的實現(xiàn)類不允許重復元素的存在。

同時,List還提供一個listiterator()方法,返回一個ListIterator接口對象,和Iterator

接口相比,Listiterator添加元素的添加,刪除,和設定等方法,還能向前或向后遍歷。

List跟Collection的關系:

java.util.Collection[I]

+一一java.util.List[I]

+-java.util.ArrayList[C]

+--java.util.LinkedList[C]

+一java.util.Vector[C]

+--java.util.Stack[C]

List接口的實現(xiàn)類主要有ArrayList,LinkedList,Vector,Stack等。

本文主要對上面提到的幾個類作一個比較,說明它們的異同點以及性能上的區(qū)別等。

ArrayList,LinkedList,Vector,Stack的相同點

ArrayList,LinkedList,Vector,Stack等類都實現(xiàn)了List接口,都屬于List集合。

List接口里定義的基本方法是一樣的。

publicinterfaceList

extendsCollection

(

//...otherCollectionmethods

〃根據(jù)索引取得元素

publicabstractObjectget(inti);

〃在指定位置(索引)處插入新的元素

publicabstractObjectset(inti,Objectobj);

〃在List的尾部插入新的元素

publicabstractvoidadd(inti,Objectobj);

〃刪除指定位置(索引)處的元素

publicabstractObjectremove(inti);

〃取得指定對象的最開始的索引位置

publicabstractintindexOf(Objectobj);

〃取得指定對象的最后的索引位置

publicabstractintlastlndexOf(Objectobj);

//List提供的新的遍歷方法

publicabstractListiteratorlistiterator();

〃從指定位置i處開始迭代。最初next()方法返回的將是位置i處的元素。

publicabstractListiteratorlistiterator(inti);

〃取得從位置i到j的所有元素(包含i但不包含j位置的元素),返回一個新的集合

對象。

publicabstractListsubList(inti,intj);

)

ArrayList,LinkedList,Vector,Stack的相異之處:

數(shù)據(jù)構造上的差異:

ArrayList,Vector,Stack都是使用動態(tài)數(shù)組來保存集合中的對象元素,亦即ArrayList,

Vector,Stack具有基本相似的數(shù)據(jù)結構。ArrayList,Vector除了以下所說的線程同步上

的差異之外,它們的功能基本一樣;Vector從Stack繼承,除了擁有Stack具有的功能之

外,還實現(xiàn)了棧的功能。

而LinkedList則使用鏈表的形式來保存集合中的對象元素。

線程處理上的差異:

ArrayList,LinkedList沒有使用synchronized對線程同步作任何處理,也就是說它們在

同一時刻可以由多個線程訪問,不是線程安全的;

Vector,Stack則使用synchronized對主要方法作了同步控制,它們在同一時刻只能由一

個線程訪問。

ArrayList.LinkedList,Vector,Stack的性能比較:

因為數(shù)據(jù)構造上的差異,它們在處理元素的添加,刪除,插入,索引取值,遍歷取值方面的

效率上也各不相同。

ArrayList,Vector,Stack都是采用動態(tài)數(shù)組,它們的處理效率基本一樣。

LinkedList采用鏈表構造,所以它跟ArrayList,Vector,Stack在添加,刪除,插入,取

值操作上就很大差異。

在具體的應用中,為了性能,功能上的考慮,我們可以根據(jù)具體的需求采用不同的List。

ArrayList,Vector,Stack

元素添加操作

ArrayList,Vector,Stack添加元素時的基本步驟是:

-確保動態(tài)數(shù)組的空間大小。若空間不夠時,則為集合元素重新分配空間,新分配的空間是

原有空間大小的L5倍左右,并把原來的集合元素拷貝到新分配的空間上。所以如果對象元

素很多,有可能分配的空間大小要遠遠多出實際的元素,所以為了內(nèi)存利用效率考慮,使用

ArrayList等時,如果事先知道元素的多少,最好初始化時為其分配最大空間。

-設置新元素到size+l位置。

大量添加時的性能:因為重新分配空間的次數(shù)不會太多,性能評價:好

元素刪除操作

-將刪除位置i以后的元素全部往前移一個位置

-設置size處元素為null

大量刪除時的性能:因為每個元素的刪除都會進行移位拷貝,性能評價:差

元素插入操作

-同元素添加操作

-將插入位置i及以后的所有元素往后移一個位置

-設置新元素至插入位置i

大量插入時的性能:因為每個元素的插入都會進行移位拷貝,性能評價:差

索引取值/遍歷取值

因為是動態(tài)數(shù)組結構,所以索引取值(根據(jù)數(shù)組的下標)的速度非???。

它們的遍歷取值(Iterator,next())的內(nèi)部實現(xiàn)是根據(jù)當前元素的位置取得下一個元素,

所以跟索引取值一樣,都是簡單地引用數(shù)組的下標,所以速度也非??臁?/p>

性能評價:極優(yōu)

LinkedList

元素添加操作

元素刪除操作

元素插入操作

LinkedList的元素添加,刪除,插入的操作步驟一樣:

-定位需要操作的元素

-執(zhí)行添加,刪除,插入操作

雖然在元素的定位操作上需要花些時間,但LinkedList在處理時對元素的定位作了優(yōu)化,

性能評價:好

索引取值

因為LinkedList的鏈表結構,所以對元素的索引取值是一個遍歷的過程,性能評價:極差

遍歷取值

LinkedList在遍歷的時候保存了當前元素,因為它的鏈表結構,可以快速的定位下一個元

素。性能評價:極優(yōu)

性能總結:

一人itera

add()操delete()操insert操index取值

tor取值

作作作操作

操作

ArrayList/Vector/好差差極極

Stack優(yōu)優(yōu)

好好好差極

LinkedList

優(yōu)

下面舉例來說明它們在性能上的區(qū)別。

代碼

viewplaincopytoclipboardprint?

packagecom.test.collection;

importjava.util.Iterator;

importjava.util.List;

publicclassTestList{

/**

*List集合性能測試類

*Usage:javacom.test.collection.TestListListClassNameMAX_TIMES

*例:javacom.test.collection.TestListLinkedList100000

*/

publicstaticvoidmain(String[]args){

if(args!=null&&args.length==2){

testList(args[O],Integer.parselnt(args[l]));

}else{

testList("LinkedList",20000);

testList("ArrayList",20000);

)

)

privatestaticvoidtestList(StringlistName,intmaxElements){

Listlist=null;

try(

list=(List)Class.forName("java.util."+listName).newlnstance();

}catch(Exceptione){

e.printStackTrace();

)

addElement2List(list,maxElements);

deleteElement2List(list);

insertElement2List(list/maxements);

getListElementBylndex(list);

getList日ementBylterator(list);

)

//addelementstoList

privatestaticvoidadd日ement2List(Listlist,intmax日ements){

longstart=System.currentTimeMillis();

for(inti=1;i<maxElements;i++){

list.add(newInteger(i));

}

longend=System.currentTimeMillis();

printTime(list,end-start,"[add]H);

//removeelementsfromList

privatestaticvoiddelete日ement2List(Listlist){

longstart=System.currentTimeMillis();

while(!list.isEmpty()){

list.remove(O);

)

longend=System.currentTimeMillis();

printTime(list,end-start,"[delete]");

//insertelementstoList

privatestaticvoidinsert日ement2List(Listlist,intmaxElements){

longstart=System.currentTimeMillis();

for(inti=1;i<maxElements;i++){

list.add(O,newInteger(i));

)

longend=System.currentTimeMillis();

printTime(list,end-start,n[insert]");

)

privatestaticvoidgetListElementBylndex(Listlist){

longstart=System.currentTimeMillis();

for(inti=1;i<list.size();i++){

Integerele=(Integer)list.get(i);

)

longend=System.currentTimeMillis();

printTime(list,end-start,"[index]");

)

privatestaticvoidgetListElementBylterator(Listlist){

longstart=System.currentTimeMillis();

Iteratorite=list.iterator();

while(ite.hasNext()){

Integerele=(lnteger)ite.next();

)

longend=System.currentTimeMillis();

printTime(list/end-start,"[iterator]");

)

privatestaticvoidprintTime(Listlist,longtime,Stringoperation){

Stringout=list.getClass().getSimpleName();

out+=""+operation+"+time;

System.out.println(out);

執(zhí)行Client,輸出結果:

C:\test\list>javacom.test,collection.TestListArrayList100000

ArrayList[add]:79

ArrayList[delete]:8703

ArrayList[insert]:9281

ArrayList[index]:0

ArrayList[iterator]:16

C:\test\list>javacom.test.collection.TestListLinkedList100000

LinkedList[add]:125

LinkedList[delete]:16

LinkedList[insert]:78

LinkedList[index]:80328

LinkedList[iterator]:0

C:\test\list>javacom.test,collection.TestListVector100000

Vector[add]:63

Vector[delete]:8546

Vector[insert]:9422

Vector[index]:16

Vector[iterator]:0

C:\test\list>javacom.test,collection.TestListStack100000

Stack[add]:47

Stack[delete]:8593

Stack[insert]:9610

Stack[index]:0

Stack[iterator]:16

總結:

本文主要比較了ArrayList,Vector,Stack與LinkedList的操作性能。

ArrayList,Vector與Stack在索引取值,迭代取值上有較高的性能。

LinkedList在刪除,插入,迭代取值上有較高的性能。

JAVA集合類(大公司面試喜歡問的)

看了一些所謂大公司的JAVA面試問題,發(fā)現(xiàn)對于JAVA集合類的使用都比較看重似的,而自

己在這方面還真的是所真甚少,抽空也學習學習吧。

java.util包中就包含了一系列重要的集合類,而對于集合類,主要需要掌握的就是它的內(nèi)部

結構,以及遍歷集合的迭代模式。

接口:Collection

所有集合類的根類型,主要的一個接口方法:booleanadd(Ojbectc)

雖返回的是boolean,但不是表示添加成功與否,因為Collection規(guī)定:一個集合拒絕添加

這個元素,無論什么原因,都必須拋出異常,這個返回值表示的意義是add()執(zhí)行后,集合

的內(nèi)容是否改了(就是元素有無數(shù)量、位置等變化)。類似的addAII,remove,removeAIL

remainAII也是一樣的。

用Iterator模式實現(xiàn)遍歷集合

Collection有一個重要的方法:iterator。,返回一個Iterator(迭代子),用于遍歷集合的所有

元素。Iterator模式可以把訪問邏輯從不同類的集合類中抽象出來,從而避免向客戶端暴露

集合的內(nèi)部結構。

for(Iteratorit=c.iterator();it.hasNext();){...}

不需要維護遍歷集合的“指針”,所有的內(nèi)部狀態(tài)都有Iterator來維護,而這個Iterator山集

合類通過工廠方法生成。

每一種集合類返回的Iterator具體類型可能不同,但它們都實現(xiàn)了Iterator接口,因此,我

們不需要關心到底是哪種Iterator,它只需要獲得這個Iterator接口即可,這就是接口的好處,

面向對象的威力。

要確保遍歷過程順利完成,必須保證遍歷過程中不更改集合的內(nèi)容(Iterator的remove。方

法除外),所以,確保遍歷可靠的原則是:只在一個線程中使用這個集合,或者在多線程中

對遍歷代碼進行同步。

JAVAM叩集合類介紹

直接貼鏈接好了

/article/54/54534.shtm

線性表,鏈表,哈希表是常用的數(shù)據(jù)結構,在進行Java開發(fā)時,JDK已經(jīng)為我們提供了一系

列相應的類來實現(xiàn)基本的數(shù)據(jù)結構。這些類均在java.util包中。本文試圖通過簡單的描述,

向讀者闡述各個類的作用以及如何正確使用這些類。

Collection

|-List

IpLinkedList

卜ArrayList

ILVector

|LStack

LSet

Map

卜Hashtable

[-HashMap

LWeakHashMap

Collection接口

Collection是最基本的集合接口,一個Collection代表一組Object,即Collection的元素

(Elements)o一些Collection允許相同的元素而另一些不行。一些能排序而另一些不行。Java

SDK不提供直接繼承自Collection的類,JavaSDK提供的類都是繼承自Collection的“子接口”

如List和Seto

所有實現(xiàn)Collection接口的類都必須提供兩個標準的構造函數(shù):無參數(shù)的構造函數(shù)用于

創(chuàng)建一個空的Collection,有一個Collection參數(shù)的構造函數(shù)用于創(chuàng)建一個新的Collection,

這個新的Collection與傳入的Collection有相同的元素。后一個構造函數(shù)允許用戶復制一個

Collectiono

如何遍歷Collection中的每一個元素?不論Collection的實際類型如何,它都支持一個

iterator。的方法,該方法返回一個迭代子,使用該迭代子即可逐一訪問Collection中每一個

元素。典型的用法如下:

Iteratorit=collection.iterator();//獲得一個迭代子

while(it.hasNext()){

Objectobj=it.next();//得到下一個元素

)

由Collection接口派生的兩個接口是List和Seto

List接口

List是有序的Collection,使用此接口能夠精確的控制每個元素插入的位置。用戶能夠使

用索引(元素在List中的位置,類似于數(shù)組下標)來訪問List中的元素,這類似于Java的數(shù)

組。

和下面要提到的Set不同,List允許有相同的元素。

除了具有Collection接口必備的iterator。方法外,List還提供一個listlterator。方法,返

回一個Listiterator接口,和標準的Iterator接口相比,Listiterator多了?些add()之類的方法,

允許添加,刪除,設定元素,還能向前或向后遍歷。

實現(xiàn)List接口的常用類有LinkedList,ArrayList,Vector和Stack。

LinkedList類

LinkedList實現(xiàn)了List接口,允許null元素。此外LinkedList提供額外的get,remove,insert

方法在LinkedList的首部或尾部。這些操作使LinkedList可被用作堆棧(stack),隊列(queue)

或雙向隊列(deque)。

注意LinkedList沒有同步方法。如果多個線程同時訪問個List,則必須自己實現(xiàn)訪問

同步。一種解決方法是在創(chuàng)建List時構造一個同步的List:

Listlist=Collections.synchronizedList(newLinkedList(…));

ArrayList類

ArrayList實現(xiàn)了可變大小的數(shù)組。它允許所有元素,包括null。ArrayList沒有同步。

size,isEmpty,get,set方法運行時間為常數(shù)。但是add方法開銷為分攤的常數(shù),添加n個

元素需要0(n)的時間。其他的方法運行時間為線性。

每個ArrayList實例都有一個容量(Capacity),即用于存儲元素的數(shù)組的大小。這個容量

可隨著不斷添加新元素而自動增加,但是增長算法并沒有定義。當需要插入大量元素時,在

插入前可以調(diào)用ensureCapacity方法來增加ArrayList的容量以提高插入效率。

和LinkedList一樣,ArrayList也是非同步的(unsynchronized)。

Vector類

Vector非常類似ArrayList,但是Vector是同步的。由Vector創(chuàng)建的Iterator,雖然和

ArrayList創(chuàng)建的Iterator是同一接口,但是,因為Vector是同步的,當一個Iterator被創(chuàng)建

而且正在被使用,另一個線程改變了Vector的狀態(tài)(例如,添加或刪除了一些元素),這時

調(diào)用Iterator的方法時將拋出ConcurrentModificationException,因此必須捕獲該異常。

Stack類

Stack繼承自Vector,實現(xiàn)一個后進先出的堆棧。Stack提供5個額外的方法使得Vector

得以被當作堆棧使用?;镜膒ush和pop方法,還有peek方法得到棧頂?shù)脑?,empty方

法測試堆棧是否為空,search方法檢測一個元素在堆棧中的位置。Stack剛創(chuàng)建后是空棧。

Set接口

Set是一種不包含重復的元素的Collection,即任意的兩個元素el和e2都有

el.equals(e2)=false,Set最多有一個null元素。

很明顯,Set的構造函數(shù)有一個約束條件,傳入的Collection參數(shù)不能包含重復的元素。

請注意:必須小心操作可變對象(MutableObject),如果-一個Set中的可變元素改變了

自身狀態(tài)導致Object.equals(Object);true將導致一些問題。

Map接口

請注意,Map沒有繼承Collection接口,Map提供key到value的映射。一個Map中不

能包含相同的key,每個key只能映射一個value。Map接口提供3種集合的視圖,Map的

內(nèi)容可以被當作一組key集合,一組value集合,或者--組key-value映射。

Hashtable類

Hashtable繼承Map接口,實現(xiàn)一個key-value映射的哈希表。任何非空(non-null)的

對象都可作為key或者valueo

添加數(shù)據(jù)使用put(key,value),取出數(shù)據(jù)使用get(key),這兩個基本操作的時間開銷為常

數(shù)。

Hashtable通過initialcapacity和loadfactor兩個參數(shù)調(diào)整性能。通常缺省的loadfactor0.75

較好地實現(xiàn)了時間和空間的均衡。增大loadfactor可以節(jié)省空間但相應的查找時間將增大,

這會影響像get和put這樣的操作。

使用Hashtable的簡單示例如下,將1,2,3放到Hashtable中,他們的key分別是“one",”

two","three”:

Hashtablenumbers=newHashtable();

numbers.put(“one”,newInteger(l));

numbers.put(“two”,newlnteger(2));

numbers.put("three”,newlnteger(3));

要取出一個數(shù),比如2,用相應的key:

Integern=(lnteger)numbers.get(“two");

System.out.println(utwo="+n);

山于作為key的對象將通過計算其散列函數(shù)來確定與之對應的value的位置,因此任何

作為key的對象都必須實現(xiàn)hashCode和equals方法。hashCode和equals方法繼承自根類

Object,如果你用自定義的類當作key的話,要相當小心,按照散列函數(shù)的定義,如果兩個

對象相同,即objl.equals(obj2)=true,則它們的hashCode必須相同,但如果兩個對象不同,

則它們的hashCode不一定不同,如果兩個不同對象的hashCode相同,這種現(xiàn)象稱為沖突,

沖突會導致操作哈希表的時間開銷增大,所以盡量定義好的hashCode。方法,能加快哈希表

的操作。

如果相同的對象有不同的hashCode,對哈希表的操作會出現(xiàn)意想不到的結果(期待的

get方法返回null),要避免這種問題,只需要牢記一條:要同時復寫equals方法和hashCode

方法,而不要只寫其中一個。

Hashtable是同步的。

HashMap類

HashMap和Hashtable類似,不同之處在于HashMap是非同步的,并且允許null,即

nullvalue和nullkey。,但是將HashMap視為Collection時(values。方法可返回Collection),

其迭代子操作時間開銷和HashMap的容量成比例。因此,如果迭代操作的性能相當重要的

話,不要將HashMap的初始化容量設得過高,或者loadfactor過低。

WeakHashMap類

WeakHashMap是一種改進的HashMap,它對key實行“弱引用”,如果一個key不再被

外部所引用,那么該key可以被GC回收。

總結

如果涉及到堆棧,隊列等操作,應該考慮用List,對于需要快速插入,刪除元素,應該

使用LinkedList,如果需要快速隨機訪問元素,應該使用ArrayList?

如果程序在單線程環(huán)境中,或者訪問僅僅在一個線程中進行,考慮非同步的類,其效率

較高,如果多個線程可能同時操作一個類,應該使用同步的類。

要特別注意對哈希表的操作,作為key的對象要正確復寫equals和hashCode方法。

盡量返回接口而非實際的類型,如返回List而非ArrayList,這樣如果以后需要將ArrayList換

成LinkedList時,客戶端代碼不用改變。這就是針對抽象編程。

java.util中的集合類包含Java中某些最常用的類。最常用的集合類是List和Map。List

的具體實現(xiàn)包括ArrayList和Vector,它們是可變大小的列表,比較適合構建、存儲和操作

任何類型對象的元素列表。List適用于按數(shù)值索引訪問元素的情形。

Map提供了一個更通用的元素存儲方法?M叩集合類用于存儲元素對(稱作"鍵"和"值"),

其中每個鍵映射到?個值。從概念上而言,您可以將List看作是具有數(shù)值鍵的Map。而

實際上,除了List和Map都在定義java.util中外,兩者并沒有直接的聯(lián)系。本文將著重

介紹核心Java發(fā)行套件中附帶的Map,同時還將介紹如何采用或實現(xiàn)更適用于您應用程

序特定數(shù)據(jù)的專用M叩。

了解Map接口和方法

Java核心類中有很多預定義的M叩類.在介紹具體實現(xiàn)之前,我們先介紹一下Map接

口本身,以便了解所有實現(xiàn)的共同點。Map接口定義了四種類型的方法,每個Map都包

含這些方法。下面,我們從兩個普通的方法(表1)開始對這些方法加以介紹。

表1:覆蓋的方法。我們將這Object的這兩個方法覆蓋,以正確比較Map對象的等價

性。

equals(Objecto)比較指定對象與此Map的等價性

hashCode()返回此Map的哈希碼

Map構建

Map定義了幾個用于插入和刪除元素的變換方法(表2)?

表2:Map更新方法:可以更改Map內(nèi)容。

clear()從Map中刪除所有映射

remove(Objectkey)從Map中刪除鍵和關聯(lián)的值

put(Objectkey,Objectvalue)將指定值與指定鍵相關聯(lián)

clear()從Map中刪除所有映射

putAII(Mapt)將指定Map中的所有映射復制到此map

盡管您可能注意到,縱然假設忽略構建一個需要傳遞給的的開銷,使用

PutAII()Map

putAIIO通常也并不比使用大量的put()調(diào)用更有效率,但putAII()的存在一點也不稀奇。

這是因為,putAIIO除了迭代put()所執(zhí)行的將每個鍵值對添加到Map的算法以外,還需

要迭代所傳遞的Map的元素。但應注意,putAIIO在添加所有元素之前可以正確調(diào)整Map

的大小,因此如果您未親自調(diào)整Map的大小(我們將對此進行簡單介紹),貝IJputAII()可

能比預期的更有效。

查看Map

迭代Ma

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論