更新時間:2019-12-10 10:37:21 來源:動力節點 瀏覽2317次
List、Set、Map是否繼承自Collection接口?
答:List、Set 是,Map 不是。Map是鍵值對映射容器,與List和Set有明顯的區別,而Set存儲的零散的元素且不允許有重復元素(數學中的集合也是如此),List是線性結構的容器,適用于按數值索引訪問元素的情形。
闡述ArrayList、Vector、LinkedList的存儲性能和特性。
答:ArrayList 和Vector都是使用數組方式存儲數據,此數組元素數大于實際存儲的數據以便增加和插入元素,它們都允許直接按序號索引元素,但是插入元素要涉及數組元素移動等內存操作,所以索引數據快而插入數據慢,Vector中的方法由于添加了synchronized修飾,因此Vector是線程安全的容器,但性能上較ArrayList差,因此已經是Java中的遺留容器。LinkedList使用雙向鏈表實現存儲(將內存中零散的內存單元通過附加的引用關聯起來,形成一個可以按序號索引的線性結構,這種鏈式存儲方式與數組的連續存儲方式相比,內存的利用率更高),按序號索引數據需要進行前向或后向遍歷,但是插入數據時只需要記錄本項的前后項即可,所以插入速度較快。Vector屬于遺留容器(Java早期的版本中提供的容器,除此之外,Hashtable、Dictionary、BitSet、Stack、Properties都是遺留容器),已經不推薦使用,但是由于ArrayList和LinkedListed都是非線程安全的,如果遇到多個線程操作同一個容器的場景,則可以通過工具類Collections中的synchronizedList方法將其轉換成線程安全的容器后再使用(這是對裝潢模式的應用,將已有對象傳入另一個類的構造器中創建新的對象來增強實現)。
補充:遺留容器中的Properties類和Stack類在設計上有嚴重的問題,Properties是一個鍵和值都是字符串的特殊的鍵值對映射,在設計上應該是關聯一個Hashtable并將其兩個泛型參數設置為String類型,但是Java API中的Properties直接繼承了Hashtable,這很明顯是對繼承的濫用。這里復用代碼的方式應該是Has-A關系而不是Is-A關系,另一方面容器都屬于工具類,繼承工具類本身就是一個錯誤的做法,使用工具類最好的方式是Has-A關系(關聯)或Use-A關系(依賴)。同理,Stack類繼承Vector也是不正確的。Sun公司的工程師們也會犯這種低級錯誤,讓人唏噓不已。
Collection和Collections的區別?
答:Collection是一個接口,它是Set、List等容器的父接口;Collections是個一個工具類,提供了一系列的靜態方法來輔助容器操作,這些方法包括對容器的搜索、排序、線程安全化等等。
List、Map、Set三個接口存取元素時,各有什么特點?
答:List以特定索引來存取元素,可以有重復元素。Set不能存放重復元素(用對象的equals()方法來區分元素是否重復)。Map保存鍵值對(key-value pair)映射,映射關系可以是一對一或多對一。Set和Map容器都有基于哈希存儲和排序樹的兩種實現版本,基于哈希存儲的版本理論存取時間復雜度為O(1),而基于排序樹版本的實現在插入或刪除元素時會按照元素或元素的鍵(key)構成排序樹從而達到排序和去重的效果。
TreeMap和TreeSet在排序時如何比較元素?Collections工具類中的sort()方法如何比較元素?
答:TreeSet要求存放的對象所屬的類必須實現Comparable接口,該接口提供了比較元素的compareTo()方法,當插入元素時會回調該方法比較元素的大小。TreeMap要求存放的鍵值對映射的鍵必須實現Comparable接口從而根據鍵對元素進行排序。Collections工具類的sort方法有兩種重載的形式,第一種要求傳入的待排序容器中存放的對象比較實現Comparable接口以實現元素的比較;第二種不強制性的要求容器中的元素必須可比較,但是要求傳入第二個參數,參數是Comparator接口的子類型(需要重寫compare方法實現元素的比較),相當于一個臨時定義的排序規則,其實就是通過接口注入比較元素大小的算法,也是對回調模式的應用(Java中對函數式編程的支持)。
Thread類的sleep()方法和對象的wait()方法都可以讓線程暫停執行,它們有什么區別?
答:sleep()方法(休眠)是線程類(Thread)的靜態方法,調用此方法會讓當前線程暫停執行指定的時間,將執行機會(CPU)讓給其他線程,但是對象的鎖依然保持,因此休眠時間結束后會自動恢復(線程回到就緒狀態,請參考第66題中的線程狀態轉換圖)。wait()是Object類的方法,調用對象的wait()方法導致當前線程放棄對象的鎖(線程暫停執行),進入對象的等待池(wait pool),只有調用對象的notify()方法(或notifyAll()方法)時才能喚醒等待池中的線程進入等鎖池(lock pool),如果線程重新獲得對象的鎖就可以進入就緒狀態。
補充:可能不少人對什么是進程,什么是線程還比較模糊,對于為什么需要多線程編程也不是特別理解。簡單的說:進程是具有一定獨立功能的程序關于某個數據集合上的一次運行活動,是操作系統進行資源分配和調度的一個獨立單位;線程是進程的一個實體,是CPU調度和分派的基本單位,是比進程更小的能獨立運行的基本單位。線程的劃分尺度小于進程,這使得多線程程序的并發性高;進程在執行時通常擁有獨立的內存單元,而線程之間可以共享內存。使用多線程的編程通常能夠帶來更好的性能和用戶體驗,但是多線程的程序對于其他程序是不友好的,因為它可能占用了更多的CPU資源。當然,也不是線程越多,程序的性能就越好,因為線程之間的調度和切換也會浪費CPU時間。時下很時髦的Node.js就采用了單線程異步I/O的工作模式。
線程的sleep()方法和yield()方法有什么區別?
答:1、sleep()方法給其他線程運行機會時不考慮線程的優先級,因此會給低優先級的線程以運行的機會;yield()方法只會給相同優先級或更高優先級的線程以運行的機會;
2、 線程執行sleep()方法后轉入阻塞(blocked)狀態,而執行yield()方法后轉入就緒(ready)狀態;
3、sleep()方法聲明拋出InterruptedException,而yield()方法沒有聲明任何異常;
4、sleep()方法比yield()方法(跟操作系統CPU調度相關)具有更好的可移植性。
當一個線程進入一個對象的synchronized方法A之后,其它線程是否可進入此對象的synchronized方法B?
答:不能。其它線程只能訪問該對象的非同步方法,同步方法則不能進入。因為非靜態方法上的synchronized修飾符要求執行方法時要獲得對象的鎖,如果已經進入A方法說明對象鎖已經被取走,那么試圖進入B方法的線程就只能在等鎖池(注意不是等待池哦)中等待對象的鎖。
請說出與線程同步以及線程調度相關的方法。
答:wait():使一個線程處于等待(阻塞)狀態,并且釋放所持有的對象的鎖;
sleep():使一個正在運行的線程處于睡眠狀態,是一個靜態方法,調用此方法要處理InterruptedException異常;
notify():喚醒一個處于等待狀態的線程,當然在調用此方法的時候,并不能確切的喚醒某一個等待狀態的線程,而是由JVM確定喚醒哪個線程,而且與優先級無關;
notityAll():喚醒所有處于等待狀態的線程,該方法并不是將對象的鎖給所有線程,而是讓它們競爭,只有獲得鎖的線程才能進入就緒狀態。
提示:關于Java多線程和并發編程的問題,建議大家看我的另一篇文章《關于Java并發編程的總結和思考》。
補充:Java 5通過Lock接口提供了顯式的鎖機制(explicit lock),增強了靈活性以及對線程的協調。Lock接口中定義了加鎖(lock())和解鎖(unlock())的方法,同時還提供了newCondition()方法來產生用于線程之間通信的Condition對象;此外,Java 5還提供了信號量機制(semaphore),信號量可以用來限制對某個共享資源進行訪問的線程的數量。在對資源進行訪問之前,線程必須得到信號量的許可(調用Semaphore對象的acquire()方法);在完成對資源的訪問后,線程必須向信號量歸還許可(調用Semaphore對象的release()方法)。
以上就是動力節點Java培訓機構小編介紹的“2019年最新Java面試題整合”的內容,希望對大家有幫助,如有疑問,請在線咨詢,有專業老師隨時為你服務。
相關推薦
最新最全java面試題及答案(初級到高級)
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習