Java_面試札記
為了不死,我願獻出生命
背景:記錄下寄幾和friend在2020年Java面試中遇到的problem。
1、MySQL索引結構?
基本上所有的索引都是B-Tree結構,還有一部分是HASH索引;B-Tree資料結構的簡單說明:
1、B-Tree結構首先是分成很多節點,一個節點上面有很多的關鍵字(建立索引的欄位),這些關鍵字在節點上是按照順序排列的;
2、在一個節點上,每一個關鍵字的前面都有一個下個節點的指標,所以在一個節點上面,關鍵字的數量總是比節點的數量少一個;
3、每個節點指標指向下一個節點。
2、MySQL索引分類?
1、普通索引index:加速查詢;
2、唯一索引
主鍵索引:primary key:加速查詢+約束(不為空且唯一);
唯一索引:unique:加速查詢+約束(唯一);
3、聯合索引
-primary key(id,name);聯合主鍵索引
-unique(id,name);聯合唯一索引
-index(id,name);聯合普通索引
索引按照功能分類:
1、主鍵索引:一張表中最多有一個主鍵索引,且欄位不能為NULL,不能重複;
2、唯一索引:一張表中可以有多個唯一索引,且欄位可以為NULL,但不能有重複值;
3、普通索引:一張表中可以有多個普通索引,且值可以為NULL,並且值可以重複;
4、全文索引:全文索引就是將該欄位的資訊加以拆分和組合,形成一份清單,和sphinx全文索引一樣;
5、複合索引:一個索引如果建立在多個欄位上,那該索引就稱為複合索引。
說明:其實這些索引的資料結構都是一樣的B-Tree結構,只是他們對欄位資訊的約束條件不一樣。
4、索引的使用有了解?
使用索引應該滿足左原則,如:
1、like查詢時,不能以萬用字元開始;
2、複合索引,如果想使用第二個關鍵字索引,那麼第一個關鍵字索引必須要確定;
5、對A、B、C三個欄位建立聯合索引,然後使用ABC三個欄位查詢,哪個欄位會擊中索引?
根據查詢欄位的位置不同來決定,如查詢A、A,B、A,B,C、A,C都可以走索引的,其它條件的查詢不走索引;組合索引有“最左字首”原則,就是隻從最左面的開始組合,並不是所有隻要含有這三列存在的欄位的查詢都會用到該組合索引。
6、ES處理資料?
ElasticSearch是一個開源的搜尋引擎。
ES的簡介及使用:https://www.cnblogs.com/wihainan/p/7064943.html
7、Java中物件作為引數傳遞,是傳值還是傳引用?
在Java中,當物件最為引數傳遞時,實際上傳遞的是一份“引用的拷貝”,即實際傳遞的是物件的引用。
8、new一個物件是如何儲存的?
堆記憶體是用來存放由new建立的物件和陣列,即動態申請的記憶體都存放在堆記憶體中;
棧記憶體是用來存放在函式中定義的一些基本型別的變數和物件的引用變數;
如:new一個person,Person person = new Person();右邊部分new Person()儲存在堆中,左邊物件的引用person儲存在棧中。
9、解釋性SQL?
explain select name from table;explain顯示了MySQL如何使用索引來處理select語句以及連線表,可以幫助選擇更好的索引和寫出更優化的查詢語句。
10、Linux命令檢視檔案大小?
ll -lht, ls -l
11、Linux命令檢視記憶體大小?
free -m
12、Spring中的FactoryBean和BeanFactory的區別?
BeanFactory是個Factory,也就是IOC容器或物件工廠,FactoryBean是個Bean;
在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)來進行管理的;(這些bean為普通bean)
但對FactoryBean而言,這個Bean不是簡單的bean,而是一個能生產或者修飾物件生成的工廠Bean,它的實現與設計模式中的工廠模式和修飾器模式類似。(非普通bean)
13、分庫分表按照什麼規則?
清瀾山的智慧校園系統是按照業務實現分庫的,如人員資料庫、車輛資料庫、主資料資料庫等;
分表可以水平分割、垂直分割;
水平分割:表中資料量大時,可以適當的進行水平分割,將部分資料移動到另一張表中;
垂直分割:表中欄位過多時,可以適當的進行垂直分割,將部分欄位移動到另一張表中。
14、SpringBoot的啟動過程?
1、啟動類中呼叫:SpringApplication.run(xxx.class,args)方法;
2、在SpringApplication的run方法中有兩個步驟,首先建立SpringApplication物件,然後再呼叫run方法;
3、在SpringApplication構造器中呼叫initialize(sources)方法;
4、在initialize方法中:
a、將sources轉換成list加到this.sources屬性中;
b、判斷是否為Web環境(在類路徑下是否可以載入到Servlet和ConfigurableWebApplicationContext);
c、載入initializers(通過META-INF/spring.factories中鍵為 ApplicationContextInitialzer的配置進行載入),debug發現一共載入了6個initializer(spring-boot-1.5.10.RELEASE.jar中四個,autoconfigure-1.5.10-RELEASE.jar中兩個);
d、載入ApplicationListener(也是通過META-INF/spring.factories),debug發現共載入了10個;
e、通過尋找main方法找到主啟動類;
5、run方法中
a、StopWatch主要時監控啟動過程,統計啟動時間,檢測應用是否已啟動或者停止;
b、載入SpringApplicationRunListener(也是通過META-INF/spring.factories),預設載入的是EventPublishingRunListener;
c、呼叫RunListener.starting()方法;
d、根據args建立應用引數解析器ApplicationArguments;
e、準備環境變數:獲取環境變數environment,將應用引數放入到環境變數持有物件中,監聽監聽器環境變數物件的變化;(listener.environmentPrepared)
f、列印Banner資訊;(SpringBootBanner)
g、建立SpringBoot的應用上下文(AnnotationConfigEmbeddedWebApplicationContext)
h、prepareContext 上下文之前的準備;
i、refreshContext重新整理上下文;
j、afterRefresh(ApplicationRunner,CommandLineRunner 介面實現類的啟動);
k、返回上下文物件;
15、AOP和IOC採用的設計模式?
aop:代理模式;
ioc:工廠模式;
16、在分散式系統中如何合併多個服務的日誌?(每個日誌檔案大小約300M,合併成一個日誌檔案)
使用歸併演算法,可以為每個檔案分配一個40M的陣列,再另外分配一個400M的陣列儲存歸併結果,每個檔案每次讀取40M,對十個陣列做歸併排序直到其中某個陣列的資料被處理完,這時將歸併結果寫入磁碟,處理完的陣列繼續讀入40M,繼續參與歸併,以此類推,直到所有檔案都處理完。
17、HashMap連結串列轉為紅黑樹,為什麼一定要連結串列長度為8的時候呢?7、9它不可以嗎?
選擇8是從時間複雜度考慮的,從8開始用樹效率更好;紅黑樹的平均查詢長度,也就是時間複雜度log(n),長度為8,查詢長度log(8)=3,因為2的三次方是8;連結串列的平均查詢為n/2,當長度為8時,平均查詢長度為8/2=4,這時才有轉換成樹的必要,因為log(8)比8/2小,用樹結構需要的查詢步數更小。
18、HashMap擴容,為什麼是以2的冪次方增長,不是3、4?
HashMap計算新增元素的位置時,使用的是位運算,這是特別高效的運算;另外,HashMap的初始容量是2的n次冪,擴容也是2倍的形式進行擴容,是因為容量是2的n次冪,只需要判斷高位hash,移動到之前到位置的倍數就可以了,免去了重新計算位置的運算,可以使得新增的元素均勻分佈在HashMap中的陣列上,減少hash碰撞,避免形成連結串列的結構,使得查詢效率降低。
19、HashMap初始化容量設定多少合適?如果設定為7,其容量是多少?
當我們使用HashMap(int initialCapacity)來初始化容量的時候,HashMap並不會使用我們傳進來的initialCapacity 值直接作為初始容量;JDK會預設幫我們計算一個相對合理的值當作初始容量,就是找到第一個比使用者傳入的值大的2的冪;如當我們new HashMap(7)建立HashMap的時候,JDK會通過計算,幫我們建立一個容量為8(2的三次冪)的Map;當我們new HashMap(9)建立HashMap的時候,DK會通過計算,幫我們建立一個容量為16(24)的Map。所以,可以根據業務需求來給HashMap設定一個初始化容量,如果明確知道一個HashMap的容量為7時,可以通過newHashMapWithExpectedSize(7)建立HashMap;
Map<String,String> map = Maps.newHashMapWithExpectedSize(7);
通過該方法建立Map就不會導致HashMap自動擴容,影響效能,是一種用記憶體換效能的做法。
20、鎖的底層原理?為什麼能夠鎖住?
1、synchronized是通過監視器鎖(monitor)實現的;
2、Lock底層是通過AQS實現的,採用執行緒獨佔的形式,在硬體層面依賴特殊的CPU指令(CAS);簡單來說ReenTrantLock的實現是一種自旋鎖,通過迴圈呼叫CAS操作來實現枷鎖;
3、在JVM底層volatile是採用“記憶體屏障”來實現的。
21、Mybatis的二級快取及原理?
Mybatis預設開啟一級快取,支援在同一個會話(sqlsession)同一個statement執行兩次,則第二次會預設使用第一次建立的快取物件;一級快取是sqlsession級別、二級快取是Mapper級別;Mybatis在為SqlSession物件建立Executor物件時,會對Executor物件加上一個裝飾者:CachingExecutor,這時SqlSession使用CachingExecutor物件來完成操作請求CachingExecutor對於查詢請求,會先判斷該查詢在Application級別的二級快取中是否有快取結果,如果有查詢結果,則直接返回快取結果;如果快取中沒有,再交給真正的Executor物件來完成查詢操作,之後CachingExecutor會將真正Executor返回的查詢結果放置到快取中,然後再返回給使用者;CachingExecutor是Executor的裝飾者,以增強Executor的功能,使其具有快取查詢功能,這裡用到了設計模式中的裝飾者模式。
22、既然紅黑樹這麼好,為什麼不一開始就直接用紅黑樹代替連結串列?
因為紅黑樹需要左旋、右旋操作,而單連結串列不需要;當個數不多的時候,直接遍歷更方便,實現起來也簡單,而紅黑樹的實現要複雜的多。
為了不死,我願獻出生命