HashMap、HashTable、ConCurrentHasgMap的區(qū)別以及實現(xiàn)原理?
ConCurrentHasgMap調(diào)用get()方法的時候有鎖嗎?
對于put和remove操作辨绊,是使用鎖同步來進(jìn)行的,不過是用的ReentrantLock而不是synchronized房待,性能上要更高一些邢羔。它們的實現(xiàn)前文都已經(jīng)提到過驼抹,就沒什么可分析的了。
使用final關(guān)鍵字修飾一個變量時拜鹤,是引用不能變框冀,還是引用的對象不能變?
使用final關(guān)鍵字修飾一個變量時敏簿,是指引用變量不能變明也,引用變量所指向的對象中的內(nèi)容還是可以改變的。例如惯裕,對于如下語句:
final StringBuffer a=new StringBuffer("immutable");
執(zhí)行如下語句將報告編譯期錯誤:
a=new StringBuffer("");
但是温数,執(zhí)行如下語句則可以通過編譯:
a.append(" broken!");
"=="和equals方法究竟有什么區(qū)別?
String a = new String("foo");
String b = new String("foo");
System.out.println(a == b);// false
System.out.println(a.equals(b));// true
默認(rèn)的equals方法
public boolean equals(Object obj) {
return (this == obj);
}
String 類重寫了 equals方法
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
是否可以從一個static方法內(nèi)部發(fā)出對非static方法的調(diào)用蜻势?
不可以撑刺。也就是說,當(dāng)一個static方法被調(diào)用時握玛,可能還沒有創(chuàng)建任何實例對象够傍,如果從一個static方法中發(fā)出對非static方法的調(diào)用,那個非static方法是關(guān)聯(lián)到哪個對象上的呢挠铲?這個邏輯無法成立冕屯,所以,一個static方法內(nèi)部發(fā)出對非static方法的調(diào)用拂苹。
Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
Math類中提供了三個與取整有關(guān)的方法:ceil安聘、floor、round瓢棒,這些方法的作用與它們的英文名稱的含義相對應(yīng)浴韭,例如,ceil的英文意義是天花板音羞,該方法就表示向上取整囱桨,Math.ceil(11.3)的結(jié)果為12,Math.ceil(-11.3)的結(jié)果是-11;floor的英文意義是地板嗅绰,該方法就表示向下取整,Math.ceil(11.6)的結(jié)果為11,Math.ceil(-11.6)的結(jié)果是-12搀继;最難掌握的是round方法窘面,它表示“四舍五入”,算法為Math.floor(x+0.5)叽躯,即將原來的數(shù)字加上0.5后再向下取整财边,所以,Math.round(11.5)的結(jié)果為12点骑,Math.round(-11.5)的結(jié)果為-11酣难。
請說出作用域public谍夭,private,protected憨募,以及不寫時的區(qū)別
這四個作用域的可見范圍如下表所示紧索。
說明:如果在修飾的元素上面沒有寫任何訪問修飾符,則表示friendly菜谣。
作用域 當(dāng)前類 同一package 子孫類 其他package
public √ √ √ √
protected √ √ √ ×
friendly √ √ × ×
private √ × × ×
備注:只要記住了有4種訪問權(quán)限珠漂,4個訪問范圍,然后將全選和范圍在水平和垂直方向上分別按排從小到大或從大到小的順序排列尾膊,就很容易畫出上面的圖了媳危。
Overloaded的方法是否可以改變返回值的類型?
至于Overloaded的方法是否可以改變返回值的類型這個問題,要看你倒底想問什么呢冈敛?這個題目很模糊待笑。如果幾個Overloaded的方法的參數(shù)列表不一樣,它們的返回者類型當(dāng)然也可以不一樣抓谴。但我估計你想問的問題是:如果兩個方法的參數(shù)列表完全一樣暮蹂,是否可以讓它們的返回值不同來實現(xiàn)重載Overload。這是不行的齐邦,我們可以用反證法來說明這個問題椎侠,因為我們有時候調(diào)用一個方法時也可以不定義返回結(jié)果變量,即不要關(guān)心其返回結(jié)果措拇,例如我纪,我們調(diào)用map.remove(key)方法時,雖然remove方法有返回值丐吓,但是我們通常都不會定義接收返回結(jié)果的變量浅悉,這時候假設(shè)該類中有兩個名稱和參數(shù)列表完全相同的方法,僅僅是返回類型不同券犁,java就無法確定編程者倒底是想調(diào)用哪個方法了术健,因為它無法通過返回結(jié)果類型來判斷。
構(gòu)造器Constructor是否可被override?
構(gòu)造器Constructor不能被繼承粘衬,因此不能重寫Override荞估,但可以被重載Overload。
面向?qū)ο蟮奶卣饔心男┓矫嬷尚拢糠庋b 繼承 多態(tài) 抽象
匿名內(nèi)部類也就是沒有名字的內(nèi)部類
正因為沒有名字勘伺,所以匿名內(nèi)部類只能使用一次,它通常用來簡化代碼編寫
但使用匿名內(nèi)部類還有個前提條件:必須繼承一個父類或?qū)崿F(xiàn)一個接口
Thread類的匿名內(nèi)部類實現(xiàn)
Runnable接口的匿名內(nèi)部類實現(xiàn)
String是最基本的數(shù)據(jù)類型嗎?
基本數(shù)據(jù)類型包括byte褂删、int飞醉、char、long屯阀、float缅帘、double轴术、boolean和short。
java.lang.String類是final類型的钦无,因此不可以繼承這個類逗栽、不能修改這個類。為了提高效率節(jié)省空間铃诬,我們應(yīng)該用StringBuffer類
是否可以繼承String類?
String類是final類故不可以繼承
重寫equals()時為什么也得重寫hashCode()之深度解讀equals方法與hashCode方法淵源
使用hashCode()和equals()
hashCode()方法被用來獲取給定對象的唯一整數(shù)祭陷。這個整數(shù)被用來確定對象被存儲在HashTable類似的結(jié)構(gòu)中的位置。默認(rèn)的趣席,Object類的hashCode()方法返回這個對象存儲的內(nèi)存地址的編號兵志。
String、Math等封裝類都對equals()方法進(jìn)行了重寫宣肚。下面是String的equals()方法想罕。
數(shù)組有沒有l(wèi)ength()這個方法? String有沒有l(wèi)ength()這個方法?
數(shù)組沒有l(wèi)ength()這個方法霉涨,有l(wèi)ength的屬性按价。String有有l(wèi)ength()這個方法。
下面這條語句一共創(chuàng)建了多少個對象:String s="a"+"b"+"c"+"d"; 一個
try {}里有一個return語句笙瑟,那么緊跟在這個try后的finally {}里的code會不會被執(zhí)行楼镐,什么時候被執(zhí)行,在return前還是后?
答案是在return之前 但是return 的結(jié)果不會被finally 的運(yùn)行改變
finally中的代碼比return和break語句后執(zhí)行
final, finally, finalize的區(qū)別往枷。
final 用于聲明屬性框产,方法和類,分別表示屬性不可變错洁,方法不可覆蓋秉宿,類不可繼承。
內(nèi)部類要訪問局部變量屯碴,局部變量必須定義成final類型描睦,例如,一段代碼……
finally是異常處理語句結(jié)構(gòu)的一部分导而,表示總是執(zhí)行忱叭。
finalize是Object類的一個方法,在垃圾收集器執(zhí)行的時候會調(diào)用被回收對象的此方法今艺,可以覆蓋此方法提供垃圾收集時的其他資源回收窑多,例如關(guān)閉文件等。JVM不保證此方法總被調(diào)用
不同類型的異常分別用不同的Java類表示洼滚,所有異常的根類為java.lang.Throwable,Throwable下面又派生了兩個子類:Error和Exception
編譯器強(qiáng)制普通異常必須try..catch處理或用throws聲明繼續(xù)拋給上層調(diào)用方法處理技潘,所以普通異常也稱為checked異常遥巴,而系統(tǒng)異城Э担可以處理也可以不處理,所以铲掐,編譯器不強(qiáng)制用try..catch處理或用throws聲明拾弃,所以系統(tǒng)異常也稱為unchecked異常。
提示答題者:就按照三個級別去思考:虛擬機(jī)必須宕機(jī)的錯誤摆霉,程序可以死掉也可以不死掉的錯誤豪椿,程序不應(yīng)該死掉的錯誤;
請寫出你最常見到的5個runtime exception携栋。
NullPointerException搭盾、ArrayIndexOutOfBoundsException、ClassCastException婉支。
啟動一個線程是用run()還是start()? .
啟動一個線程是調(diào)用start()方法鸯隅,使線程就緒狀態(tài),以后可以被調(diào)度為運(yùn)行狀態(tài)向挖,一個線程必須關(guān)聯(lián)一些具體的執(zhí)行代碼蝌以,run()方法是該線程所關(guān)聯(lián)的執(zhí)行代碼。
java中有幾種方法可以實現(xiàn)一個線程何之?用什么關(guān)鍵字修飾同步方法? stop()和suspend()方法為何不推薦使用跟畅?
new Thread(){
public void run(){
}
}.start();
new Thread(new Runnable(){
public voidrun(){
}
}
).start();
ExecutorService pool = Executors.newFixedThreadPool(3)
for(int i=0;i<10;i++)
{
pool.execute(newRunable(){public void run(){}});
}
Executors.newCachedThreadPool().execute(new Runable(){publicvoid run(){}});
Executors.newSingleThreadExecutor().execute(new Runable(){publicvoid run(){}});
用synchronized關(guān)鍵字修飾同步方法
sleep()和 wait()有什么區(qū)別?
(網(wǎng)上的答案:sleep是線程類(Thread)的方法,導(dǎo)致此線程暫停執(zhí)行指定時間溶推,給執(zhí)行機(jī)會給其他線程徊件,但是監(jiān)控狀態(tài)依然保持,到時后會自動恢復(fù)悼潭。調(diào)用sleep不會釋放對象鎖庇忌。 wait是Object類的方法,對此對象調(diào)用wait方法導(dǎo)致本線程放棄對象鎖舰褪,進(jìn)入等待此對象的等待鎖定池皆疹,只有針對此對象發(fā)出notify方法(或notifyAll)后本線程才進(jìn)入對象鎖定池準(zhǔn)備獲得對象鎖進(jìn)入運(yùn)行狀態(tài)。)
同步和異步有何異同占拍,在什么情況下分別使用他們略就?舉例說明。
如果數(shù)據(jù)將在線程間共享晃酒。例如正在寫的數(shù)據(jù)以后可能被另一個線程讀到表牢,或者正在讀的數(shù)據(jù)可能已經(jīng)被另一個線程寫過了,那么這些數(shù)據(jù)就是共享數(shù)據(jù)贝次,必須進(jìn)行同步存取崔兴。
當(dāng)應(yīng)用程序在對象上調(diào)用了一個需要花費很長時間來執(zhí)行的方法,并且不希望讓程序等待方法的返回時,就應(yīng)該使用異步編程敲茄,在很多情況下采用異步途徑往往更有效率位谋。
多線程有幾種實現(xiàn)方法?同步有幾種實現(xiàn)方法?
多線程有兩種實現(xiàn)方法,分別是繼承Thread類與實現(xiàn)Runnable接口
同步的實現(xiàn)方面有兩種堰燎,分別是synchronized,wait與notify
Object.wait():使一個線程處于等待狀態(tài)掏父,并且釋放所持有的對象的lock。
Thread.sleep():使一個正在運(yùn)行的線程處于睡眠狀態(tài)秆剪,是一個靜態(tài)方法赊淑,調(diào)用此方法要捕捉InterruptedException(中斷異常)異常。
Object.notify():喚醒一個處于等待狀態(tài)的線程仅讽,注意的是在調(diào)用此方法的時候陶缺,并不能確切的喚醒某一個等待狀態(tài)的線程,而是由JVM確定喚醒哪個線程何什,而且不是按優(yōu)先級组哩。
Object.Allnotity():喚醒所有處入等待狀態(tài)的線程,注意并不是給所有喚醒線程一個對象的鎖处渣,而是讓它們競爭伶贰。
簡述synchronized和java.util.concurrent.locks.Lock的異同?
主要相同點:Lock能完成synchronized所實現(xiàn)的所有功能
主要不同點:Lock有比synchronized更精確的線程語義和更好的性能罐栈。synchronized會自動釋放鎖黍衙,而Lock一定要求程序員手工釋放,并且必須在finally從句中釋放荠诬。Lock還有更強(qiáng)大的功能琅翻,例如,它的tryLock方法可以非阻塞方式去拿鎖柑贞。
Java集合框架是什么方椎?說出一些集合框架的優(yōu)點?
每種編程語言中都有集合钧嘶,最初的Java版本包含幾種集合類:Vector棠众、Stack、HashTable和Array有决。
為何Map接口不繼承Collection接口闸拿?
盡管Map接口和它的實現(xiàn)也是集合框架的一部分,但Map不是集合书幕,集合也不是Map新荤。因此,Map繼承Collection毫無意義台汇,反之亦然
Enumeration和Iterator接口的區(qū)別苛骨?
Enumeration的速度是Iterator的兩倍篱瞎,也使用更少的內(nèi)存。Enumeration是非持窍基礎(chǔ)的奔缠,也滿足了基礎(chǔ)的需要。但是吼野,與Enumeration相比,Iterator更加安全两波,因為當(dāng)一個集合正在被遍歷的時候瞳步,它會阻止其它線程去修改集合。
迭代器取代了Java集合框架中的Enumeration腰奋。迭代器允許調(diào)用者從集合中移除元素单起,而Enumeration不能做到。為了使它的功能更加清晰劣坊,迭代器方法名已經(jīng)經(jīng)過改善嘀倒。
如何決定選用HashMap還是TreeMap?
對于在Map中插入局冰、刪除和定位元素這類操作测蘑,HashMap是最好的選擇。然而康二,假如你需要對一個有序的key集合進(jìn)行遍歷碳胳,TreeMap是更好的選擇∧穑基于你的collection的大小挨约,也許向HashMap中添加元素會更快,將map換為TreeMap進(jìn)行有序key的遍歷产雹。
ArrayList和Vector的不同點诫惭。
(1)Vector是同步的,而ArrayList不是蔓挖。然而夕土,如果你尋求在迭代的時候?qū)α斜磉M(jìn)行改變,你應(yīng)該使用CopyOnWriteArrayList时甚。
(2)ArrayList比Vector快隘弊,它因為有同步,不會過載荒适。
(3)ArrayList更加通用梨熙,因為我們可以使用Collections工具類輕易地獲取同步列表和只讀列表。
Comparable和Comparator接口有何區(qū)別刀诬?
Comparable和Comparator接口被用來對對象集合或者數(shù)組進(jìn)行排序咽扇。Comparable接口被用來提供對象的自然排序邪财,我們可以使用它來提供基于單個邏輯的排序。
Comparator接口被用來提供不同的排序算法质欲,我們可以選擇需要使用的Comparator來對給定的對象集合進(jìn)行排序树埠。
當(dāng)一個集合被作為參數(shù)傳遞給一個函數(shù)時,如何才可以確保函數(shù)不能修改它嘶伟?
在作為參數(shù)傳遞之前怎憋,我們可以使用Collections.unmodifiableCollection(Collection c)方法創(chuàng)建一個只讀集合,這將確保改變集合的任何操作都會拋出UnsupportedOperationException九昧。
我們?nèi)绾螐慕o定集合那里創(chuàng)建一個synchronized的集合绊袋?
我們可以使用Collections.synchronizedCollection(Collection c)根據(jù)指定集合來獲取一個synchronized(線程安全的)集合。
使用JDK提供的不可變類作為Map的key铸鹰,可以避免自己實現(xiàn)hashCode()和equals()癌别。
(6)盡可能使用Collections工具類,或者獲取只讀蹋笼、同步或空的集合展姐,而非編寫自己的實現(xiàn)。它將會提供代碼重用性剖毯,它有著更好的穩(wěn)定性和可維護(hù)性圾笨。
一般會把List初始化成一個合適的大小,以減少調(diào)整大小的次數(shù)速兔。
HashMap和Hashtable之間的區(qū)別墅拭?
同步或線程安全
Null鍵和Null值
迭代值
默認(rèn)容量大小
更多HashMap和Hashtable之間的區(qū)別請點擊這里
Java 中 Set 與 List 有什么不同?
Set是一個不允許重復(fù)元素存在的集合
Set沒有索引
Set僅僅允許一個null值
Set有類:HashSet、LinkedHashMap涣狗、TreeSet
List有索引
List允許N個null值
List可以按插入順序顯示
List有類:Vector谍婉、ArrayList、LinkedList
Vector 在Java的第一個版本就引入了镀钓,也就是說vector是一個合法規(guī)范的類
ArrayList在Java1.2版本引入的穗熬,是Java 集合框架的組成部分
Vector是同步的
ArrayList是不同步的
什么類實現(xiàn)了List接口?
ArrayList
LinkedList
Vector
什么類實現(xiàn)了Set接口丁溅?
HashSet
LinkedHashSet
TreeSet
如何保證一個集合線程安全唤蔗?
Vector, Hashtable, Properties 和 Stack 都是同步的類,所以它們都線程安全的窟赏,可以被使用在多線程環(huán)境中
使用Collections.synchronizedList(list)) 方法妓柜,可以保證list類是線程安全的
使用java.util.Collections.synchronizedSet()方法可以保證set類是線程安全的
HashSet 實現(xiàn)了哪個數(shù)據(jù)結(jié)構(gòu)?
HashSet 內(nèi)部實現(xiàn)了hashmap
為什么沒有類似Iterator.add()這樣的方法來向集合中添加元素?
如果迭代器無法保證迭代的順序涯穷,那么這種說法是不清晰的(unclear)棍掐。注意的是,ListIterator就提供了add()方法拷况,因為它能保證迭代的順序作煌。
在迭代一個集合時如何避免ConcurrentModificationException?
可以使用并發(fā)集合類來遍歷集合從而避免ConcurrentModificationException異常掘殴。例如, 使用CopyOnWriteArrayList 來替代 ArrayList.
對于HashMap,還要著重了解的是初始容量(capacity)粟誓、加載因子(load factor)奏寨、自動擴(kuò)容(threshold resizing)機(jī)制。HashMap默認(rèn)初始容量是32鹰服,加載因子是0.75病瞳。閾值(threshold)=初始容量x加載因子,當(dāng)map的大小超過 閾值時获诈,則要對該哈希表進(jìn)行rehash 操作仍源,即重建內(nèi)部數(shù)據(jù)結(jié)構(gòu)(這一過程可能會引起性能問題),從而哈希表將具有大約兩倍的容量,容量通常是2的冪次方舔涎。因此,如果能估測出元素的數(shù)量逗爹,那么最好在初始化HashMap時指定合適的capacity和 load factor亡嫌。
正確 地實現(xiàn)這兩個方法是非常重要的 要實現(xiàn)它們,請遵循以下原則:
If o1.equals(o2), 那么o1.hashCode() == o2.hashCode()總為真掘而。
Ifo1.hashCode() == o2.hashCodeis 為真, 并不意味著 o1.equals(o2)也為真挟冠。
Hashtable是一種比較基礎(chǔ)的類,如果想在迭代時對map進(jìn)行修改袍睡,那么應(yīng)該使用 ConcurrentHashMap
怎樣決定何時使用HashMap何時使用TreeMap?
對 于插入知染、刪除、定位元素頻繁的操作斑胜,HashMap提供了最好的效率控淡。如果想要按key的排序來遍歷,那么TreeMap是不二選擇止潘。某些情況下掺炭,依賴集 合的大小,先向HashMap中添加元素凭戴,然后轉(zhuǎn)換為TreeMap再按key的排序進(jìn)行遍歷也許會帶來效率上的提高涧狮。
哪些集合類是線程安全的?
Vector, Hashtable, Properties and Stack都是同步的(synchronized)類,因此是線程安全的么夫,可以在多線程環(huán)境下使用. Java 1.5 Concurrent API 引入了一些允許在迭代過程中可以修改集合的并發(fā)類者冤,由于它們會在迭代時會clone一份集合,所以在多線程環(huán)境下也是安全的档痪。
Java集合框架都有哪些最佳實踐?
要根據(jù)需求來選擇正確的容器類型涉枫,例如,如果大小固定钞它,也許選擇Array就比ArrayList更明智拜银。如果想按插入順序?qū)ap進(jìn)行迭代殊鞭,那么需要選TreeMap。如果集合不允許重復(fù)尼桶,那么就應(yīng)該選Set操灿。
某些集合類允許指定初始容量,如果我們能粗略的估計下要存儲元素的數(shù)量泵督,那么我們就可能避免重新hash(rehashing)和自動擴(kuò)容(resizing)所帶來的某些性能問題趾盐。
要針對接口編程而不是針對實現(xiàn)編程,這允許我們以后可以輕松的變更實現(xiàn)小腊。
要盡可能的使用泛型以保證類型安全救鲤,從而避免運(yùn)行時的ClassCastException異常。
使用JDK提供的不可變的(immutable)類型來作為Map的鍵秩冈,從而避免自己實現(xiàn)hashCode() 和equals()方法本缠。
盡可能多的使用Collections這一工具類,因為我們可以很輕松的調(diào)用它已實現(xiàn)的算法或用來獲取只讀的入问、同步的或空的集合對象丹锹,從而避免自己實現(xiàn)。這會極大的提高代碼的復(fù)用性芬失、穩(wěn)定性楣黍,降低維護(hù)成本。
在多線程并發(fā)編程中synchronized和Volatile都扮演著重要的角色棱烂,Volatile是輕量級的synchronized租漂,它在多處理器開發(fā)中保證了共享變量的“可見性”〖彰樱可見性的意思是當(dāng)一個線程修改一個共享變量時哩治,另外一個線程能讀到這個修改的值。
Volatile變量修飾符如果使用恰當(dāng)?shù)脑挵盼觯萻ynchronized的使用和執(zhí)行成本會更低锚扎,因為它不會引起線程上下文的切換和調(diào)度。