1. 程式人生 > >java面試(進階三篇)解答

java面試(進階三篇)解答

題目來自於網路,答案是筆者整理的。僅供參考,歡迎指正

來源: https://mp.weixin.qq.com/s?__biz=MzI1NDQ3MjQxNA==&mid=2247485723&idx=1&sn=f5c3bfbfab9fe01e6d4979e4f315f024&chksm=e9c5f0aadeb279bcff0b81842f09adc1bbf0f4d2b7bb74c5b1c4749bd1bc837e76330c81cc08&scene=21&key=f02705432716b525abb21bf4b72b95d535c372bcd26a437e05deeec7eb0c79966fd85e831802f94d715c009e49871cafb21d20ca7710a496de84350b78db9317b8b4cc6562a9eed840776d9510a4b819&ascene=7&uin=MjM2OTQ3MDkzOQ%3D%3D&devicetype=Windows+7&version=6206021b&lang=zh_CN&pass_ticket=h97v%2FevjbeMS22Cec6mLcTFMVU17Iq0u%2FWtXpCY668m3AU7lLNOkKa9JdWj%2B8omE&winzoom=1

一、基礎題

  • 怎麼解決Hash衝突;(開放地址法、鏈地址法、再雜湊法、建立公共溢位區等)

  • 寫出一個必然會產生死鎖的虛擬碼;

  • Spring IoC涉及到的設計模式;(工廠模式、單利模式。。)

  • toString()方法什麼情況下需要重寫;

  • 判斷物件相等時,什麼情況下只需要重寫 equals(),什麼情況下需要重寫 equals(),hashcode()?

  • Set記憶體放的元素為什麼不可以重複,內部是如何保證和實現的?

  • 如何保證分散式快取的一致性(分散式快取一致性hash演算法?)?分散式session實現?

  • Java 8流式迭代的好處?

  • 專案中用到的JDK的哪些特性?

  • 說一下TreeMap的實現原理?紅黑樹的性質?紅黑樹遍歷方式有哪些?如果key衝突如何解決?setColor()方法在什麼時候用?什麼時候會進行旋轉和顏色轉換?

  • Spring的bean的建立時機?依賴注入的時機?

  • ArrayList和LinkList的刪除一個元素的時間複雜度;(ArrayList是O(N),LinkList是O(1));

  • CopyOnWriteArrayList是什麼;

  • 序列化和反序列化底層如何實現的(ObjectOutputStream 、ObjectInputStream、 readObject  writeObject);

  • 如何除錯多執行緒的程式;

  • 一個執行緒連著呼叫start兩次會出現什麼情況?(由於狀態只有就緒、阻塞、執行,狀態是無法由執行轉化為執行的,所以會報不合法的狀態!)

  • HashMap在什麼時候時間複雜度是O(1),什麼時候是O(n),什麼時候又是O(logn);

  • wait方法能不能被重寫?(wait是final型別的,不可以被重寫,不僅如此,notify和notifyall都是final型別的),wait能不能被中斷;

  • 一個Controller呼叫兩個Service,這兩Service又都分別呼叫兩個Dao,問其中用到了幾個資料庫連線池的連線?

二、網路基礎

  • HTTP、TCP、UDP的區別和聯絡;

  • TCP和UDP各自的優勢,知道哪些使用UDP協議的成功案例;

  • TCP和UDP各用了底層什麼協議;

  • 單個UDP報文最大容量;

  • 單個TCP報文最大容量;

  • TCP報頭格式、UDP報頭格式;

  • Server遭遇SYN Flood應當怎麼處理;

  • Web開發中如何防範XSS?

  • 拆包和粘包的問題,如何解決,如果我們的包沒有固定長度的話,我們的應用程式應該如何解決;

三、作業系統

  • 為什麼要記憶體對齊;

  • 為什麼會有大端小端,htol這一類函式的作用;

  • top顯示出來的系統資訊都是什麼含義;(重要!)

  • Linux地址空間,怎麼樣進行定址的;

  • Linux如何查詢目錄或者檔案的;

四、分散式其他

  • 分庫與分錶帶來的分散式困境與應對之策;

  • Solr如何實現全天24小時索引更新;

五、Redis

  • Redis插槽的分配(key的有效部分使用CRC16演算法計算出雜湊值,再將雜湊值對16384取餘,得到插槽值);

  • Redis主從是怎麼選取的(一種是主動切換,另一種是使用sentinel自動方式);

  • Redis複製的過程;

  • Redis佇列應用場景;

  • Redis主節點宕機了怎麼辦,還有沒有同步的資料怎麼辦;

六、系統設計開放性題目

  • 秒殺系統設計,超賣怎麼搞;

  • 你們的圖片時怎麼儲存的,對應在資料庫中時如何儲存圖片的資訊的?

  • 假如成都沒有一座消防站,現在問你要建立幾座消防站,每個消防站要配多少名消防官兵,多少輛消防車,請你拿出一個方案;

  • 基於陣列實現一個迴圈阻塞佇列;

  • 常見的ipv4地址的展現形式如“168.0.0.1”,請實現ip地址和int型別的相互轉換。(使用位移的方式)

  • 現網某個服務部署在多臺Liunx伺服器上,其中一臺突然出現CPU 100%的情況,而其他伺服器正常,請列舉可能導致這種情況發生的原因?如果您遇到這樣的情況,應如何定位?記憶體?CPU?釋出?debug?請求量?

七、大資料量問題(後邊會有專題單獨討論)

  • 給定a、b兩個檔案,各存放50億個url,每個url各佔64位元組,記憶體限制是4G,讓你找出a、b檔案共同的url?

  • 海量日誌資料,提取出某日訪問百度次數最多的那個IP;

  • 一個文字檔案,大約有一萬行,每行一個詞,要求統計出其中最頻繁出現的前10個詞,請給出思想,給出時間複雜度分析。

此話題後邊會有專門的文章探討,如果有等不及的小夥伴,可以移步參考:

1、https://blog.csdn.net/v_july_v/article/details/6279498

2、https://blog.csdn.net/v_july_v/article/details/7382693

八、邏輯思維題

  • 有兩根粗細均勻的香(燒香拜佛的香),每一根燒完都花一個小時,怎麼樣能夠得到15min?

  • 假定你有8個撞球,其中有1個球比其他的球稍重,如果只能利用天平來斷定哪一個球重,要找到較重的球,要稱幾次?(2次);

  • 實驗室裡有1000個一模一樣的瓶子,但是其中的一瓶有毒。可以用實驗室的小白鼠來測試哪一瓶是毒藥。如果小白鼠喝掉毒藥的話,會在一個星期的時候死去,其他瓶子裡的藥水沒有任何副作用。請問最少用多少隻小白鼠可以在一個星期以內查出哪瓶是毒藥;(答案是10只)

  • 假設有一個池塘,裡面有無窮多的水。現有2個空水壺,容積分別為5升和6升。問題是如何只用這2個水壺從池塘裡取得3升的水;

 

參考答案

一、基礎題

 

1.怎麼解決Hash衝突

    

    * 開放定址法(也稱為再雜湊法,基本思想是:當關鍵字key的雜湊地址p出現衝突時,以p為基礎,產生另一個地址p1,如果p1仍然衝突,則再以p為基礎,產生另一個地址p2..直到不再衝突)。主要有以下三種方法:

        * 線性探測再雜湊(發生衝突時,順序檢視下一個單元,直到出現空單元)

        * 二次探測再雜湊(發生衝突時,在表的左右跳躍式探測)

        * 偽隨機探測

 

    * 再雜湊法(同時構造多個不同的雜湊函式,當某一個函式構造的雜湊地址發生衝突時,再計算別的函式)

    * 鏈地址法(將所有雜湊地址為i的元素構成一個稱為同義詞鏈的單鏈表)適用於經常新增和刪除的操作

    * 建立公共溢位區(將雜湊表分為基本表和溢位表,凡是和基本表衝突的,一律填入溢位區)

    更多請參考:https://www.cnblogs.com/wuchaodzxx/p/7396599.html  

 

2.寫出一個必然會產生死鎖的虛擬碼

private static final Object a = new Object();
private static final Object b = new Object();

public void handleA(){
 synchronized(a){
     // doSomething...
     synchronized(b){
     // doSomething...
     }
 }   
}

public void handleB(){
 synchronized(b){
     // doSomething...
     synchronized(a){
     // doSomething...
     }
 }   
}

3.Spring IoC涉及到的設計模式

    簡單工廠模式、單例模式

 

4.toString()方法什麼情況下需要重寫

    預設使用的是Object.toString()方法,具體內容如下:

    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

    不需要使用類的具體資訊的時候就不需要重寫

 

5.判斷物件相等時,什麼情況下只需要重寫 equals(),什麼情況下需要重寫 equals(),hashcode()

    兩個物件比較,呼叫equals方法進行比較時,預設比較的是兩個物件是否指向同一塊記憶體地址,如果是則相等,否則不相等。

    如果想修改這種規則,即只比較物件的某些屬性是否相等的時候,那麼則需要重寫equals方法。

 

    一般來說,重寫equals方法必須也重寫hashcode方法

 

6.Set記憶體放的元素為什麼不可以重複,內部是如何保證和實現的

    我們以hashSet為例,hashSet實際是使用hashmap來實現的,hashSet的值作為hashmap的key,value為定值。我們可以通過分析hashMap的put過程來分析hashSet是如何不重複的。

    我們知道hashMap是雜湊表+連結串列的方式來實現的。通過key的hashCode來確定在雜湊表中的index,相同的key會定位到同一個index,下面就是存放Entry,entry包含key和value,會將當前key與連結串列中的元素的key逐個比較,如果都不相等則放置到連結串列頭;如果存在相等的,則重置entry的value值為當前value

 

    通過上面的過程分析可知,由於hashSet使用hashMap實現時,value值都是定值,所以不會存在相同元素

 

7.如何保證分散式快取的一致性

    分散式一致性hash演算法

 

8.Java 8流式迭代的好處

    * 程式碼更簡潔

    * 提供並行流式計算,在處理集合較大時,parallelStream()極大提高效率

    ...

 

9.專案中用到的JDK的哪些特性

    專案中使用jdk8,回答jdk8的一些新特性

Lambda 表示式 − Lambda允許把函式作為一個方法的引數(函式作為引數傳遞進方法中。
方法引用 − 方法引用提供了非常有用的語法,可以直接引用已有Java類或物件(例項)的方法或構造器。與lambda聯合使用,方法引用可以使語言的構造更緊湊簡潔,減少冗餘程式碼。
預設方法 − 預設方法就是一個在接口裡面有了一個實現的方法。
新工具 − 新的編譯工具,如:Nashorn引擎 jjs、 類依賴分析器jdeps。
Stream API −新新增的Stream API(java.util.stream) 把真正的函數語言程式設計風格引入到Java中。
Date Time API − 加強對日期與時間的處理。
Optional 類 − Optional 類已經成為 Java 8 類庫的一部分,用來解決空指標異常。
Nashorn, JavaScript 引擎 − Java 8提供了一個新的Nashorn javascript引擎,它允許我們在JVM上執行特定的javascript應用。

10.說一下TreeMap的實現原理?紅黑樹的性質?紅黑樹遍歷方式有哪些?如果key衝突如何解決?setColor()方法在什麼時候用?什麼時候會進行旋轉和顏色轉換?

    // TODO

 

11.Spring的bean的建立時機?依賴注入的時機?

    在預設情況下,啟動spring容器的時候建立物件,同時對所依賴的物件進行注入

    如果配置bean的lazy-init屬性為true,在context.getBean()時才建立物件

 

12.ArrayList和LinkList的刪除一個元素的時間複雜度

    * ArrayList O(N)

    * LinkedList O(1)

 

13.CopyOnWriteArrayList是什麼

    併發安全版本的ArrayList

 

14.序列化和反序列化底層如何實現的

    序列化:把java物件轉換為位元組序列的過程(物件序列化最主要的作用就是在傳遞和儲存物件的時候,保證物件的完整性和可傳遞性。序列化後的位元組流儲存了java物件的轉狀態以及相關的描述資訊)

    反序列化:將位元組序列恢復為java物件的過程(客戶端從檔案或網路上獲取序列化後的物件位元組流後,根據位元組流中儲存的物件狀態和描述資訊,通過反序列化重建物件)

 

    序列化演算法的操作步驟:

    * 將物件的類元資料輸出

    * 遞迴輸出類的超類描述直到不再有超類

    * 類元資料完成以後,開始從最頂層的超類輸出物件例項的實際值

    * 從上到下遞迴輸出例項的資料

 

 

    延伸:為什麼要主動定義serialVersionUID,其作用是什麼?

    需要序列化的物件需要主動實現Serializable介面,這個介面是一個標記介面,IDE會提示我們需要主動生成一個serialVersionUID,如果我們不主動生成的話,那麼IDE會在我們序列化物件的時候主動幫我們生成一個。

    那麼其作用是什麼呢?我們先看一個示例

// 1.寫一個Account類
public class Account implements Serializable {
	private int id;
	private String name;
}

// 2.使用ObjectOutputStream將Account例項儲存到一個檔案
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(new File("C:/Users/Administrator/Desktop/test1.txt")));
objectOutputStream.writeObject(new Account(1,"jack"));

// 3.修改Account類,新增一個屬性
	private int age;

// 4.這時再使用ObjectInputStream將test1.txt檔案反序列化成Account物件
// 報錯資訊如下:
java.io.InvalidClassException: cache.Account; local class incompatible: stream classdesc serialVersionUID = -3122741699590248598, local class serialVersionUID = -8634529858385187253

    將上述過程重複一遍,不同點就是建立Account類的時候主動生成一個serialVersionUID,如下所示:

public class Account implements Serializable {
	private static final long serialVersionUID = 1L;
	private int id;
	private String name;

    此時儲存後再反序列化成Account物件,可以發現,沒有報錯,Account物件成功列印

 

    總結:當我們修改了我們的類的時候,那麼當前類的預設的serialVersionUID就會改變,和以前序列化到本地的serialVersionUID不同,那麼這時候反序列檔案的時候就會報錯

 

15.如何除錯多執行緒的程式

    可使用JDI來除錯

    具體用法可參考:https://m.vipcn.com/a/332165/ 

 

16.一個執行緒連著呼叫start兩次會出現什麼情況?

    第二次執行緒會報錯,報錯內容如下:

Exception in thread "main" java.lang.IllegalThreadStateException
	at java.lang.Thread.start(Thread.java:708)
	at javacore.mulit.MyThread.main(MyThread.java:40)

    第一次呼叫start之後,threadStatus會改變(非0,0代表新建),所以第二次在呼叫會報錯

 

17.HashMap在什麼時候時間複雜度是O(1),什麼時候是O(n),什麼時候又是O(logn)

    O(1):當map中的元素雜湊碼都不衝突的時候,會均勻分配在陣列中

    O(n):當map中的元素雜湊碼都衝突的時候,實際上就變成了一個連結串列結構的資料

    O(logn):map中的元素有部分衝突

 

18.wait方法能不能被重寫?

    wait方法屬於Object類,是final型別的,所以不能重寫,原始碼如下:

public final void wait() throws InterruptedException {
    wait(0);
}

19.一個Controller呼叫兩個Service,這兩Service又都分別呼叫兩個Dao,問其中用到了幾個資料庫連線池的連線?

    // TODO

 

未完待續...