Java_面試札記

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的簡介及使用://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、既然紅黑樹這麼好,為什麼不一開始就直接用紅黑樹代替鏈表?

因為紅黑樹需要左旋、右旋操作,而單鏈表不需要;當個數不多的時候,直接遍歷更方便,實現起來也簡單,而紅黑樹的實現要複雜的多。

 

 

為了不死,我願獻出生命