1. 程式人生 > >網際網路公司校招Java面試題總結及答案——微店、去哪兒、蘑菇街

網際網路公司校招Java面試題總結及答案——微店、去哪兒、蘑菇街

2.servlet和filter的區別。filter你在哪些地方用到過。 servlet是一種執行伺服器端的java應用程式,具有獨立於平臺和協議的特性,並且可以動態的生成web頁面,它工作在客戶端請求與伺服器響應的中間層。 1) 客戶端傳送請求至伺服器端; 2) 伺服器將請求資訊傳送至 Servlet; 3) Servlet 生成響應內容並將其傳給伺服器。響應內容動態生成,通常取決於客戶端的請求; 4) 伺服器將響應返回給客戶端。 在 Web 應用程式中,一個 Servlet 在一個時刻可能被多個使用者同時訪問。這時 Web 容器將為每個使用者建立一個執行緒來執行 Servlet。 filter是一個可以複用的代碼片段,可以用來轉換HTTP請求、響應和頭資訊。Filter不像Servlet,它不能產生一個請求或者響應,它只是修改對某一資源的請求,或者修改從某一的響應。只要你在web.xml檔案配置好要攔截的客戶端請求,它都會幫你攔截到請求,此時你就可以對請求或響應(Request、Response)統一設定編碼,簡化操作;同時還可進行邏輯判斷,如使用者是否已經登陸、有沒有許可權訪問該頁面等等工作。
Filter對使用者請求進行預處理,接著將請求交給Servlet進行處理並生成響應,最後Filter再對伺服器響應進行後處理。 建立一個Filter只需兩個步驟:
    • 建Filter處理類;
    • web.xml檔案中配置Filter。
一定要實現javax.servlet包的Filter介面的三個方法init()、doFilter()、destroy(). listener:監聽器,從字面上可以看出listener主要用來監聽只用。通過listener可以監聽web伺服器中某一個執行動作,並根據其要求作出相應的響應。 interceptor:是在面向切面程式設計的,就是在你的service或者一個方法,前呼叫一個方法,或者在方法後呼叫一個方法,是基於JAVA的反射機制。比如動態代理就是攔截器的簡單實現
3.堆與普通二叉樹有什麼區別。 堆是結點之間滿足一定次序關係的完全二叉樹(大多數情況下使用的是完全二叉樹,但不一定必須是完全二叉樹)。 具有n個結點的堆,其深度即為堆所對應的完全二叉樹的深度log n 。 以小根堆為例,堆的特點是雙親結點的關鍵字必然小於等於孩子結點的關鍵字,而兩個孩子結點的關鍵字沒有次序規定。 堆存在的原因: 我們需要能得到一個集合的最小值,並且,在它被任意劃分成為若干個子集的時候,這些子集的最小值我們也是知道的,這些子集不斷的被劃分,我們依然知道再次被劃分出來的這些子集的最小值。 堆不止二叉堆,還有更復雜的二項堆,斐波那契堆,配對堆等等。 總之,堆是一種特殊的樹。 4.linux如何查詢檔案 cat、vi、 find :find <指定目錄> <指定條件> <指定動作> 使用locate搜尋linux系統中的檔案,它比find命令快。因為它查詢的是資料庫(/var/lib/locatedb),資料庫包含本地所有的 檔案資訊。使用locate命令在根目錄下搜尋interfaces檔案的命令為”locate interfaces“ 使用”whereis“命令可以搜尋linux系統中的所有可執行檔案即二進位制檔案。使用whereis命令搜尋grep二進位制檔案的命令為”whereis grep“。 --------------------------------------------------去哪兒-------------------------------------------- 3.
類載入機制
  • 啟動類載入器( Bootstrap ClassLoader)啟動類載入器無法被 java 程式設計師直接引用, 這個類載入器負責把存放在<JAVA_HOME>\lib目錄中的, 或者被-Xbootclasspath引數指定路徑中的, 並且是被虛擬機器識別的類庫載入到虛擬機器記憶體中.
  • 擴充套件類載入器(Extension ClassLoader)負責載入在<JAVA_HOME>\lib\ext目錄中的, 或者被java.ext.dirs系統變數所指定的路徑中的所有類庫。
  • 應用程式類載入器( Application ClassLoader )這個類載入器是ClassLoader 中的 getSystemClassLoader()方法的返回值, 一般稱其為系統類載入器, 它負責載入使用者類路徑( ClassPath )上所指定的類庫
從 java 虛擬機器的角度而降, 只存在兩種不同的類載入器:
  • 一個是啟動類載入器( Bootstrap ClassLoader ), 這個類載入使用 C++ 語言實現, 是虛擬機器自身的一部分;
  • 另一種是其他所有的類載入器, 他們由 java 語言實現, 獨立於虛擬機器之外, 並且全部繼承自java.lang.ClassLoader
載入類的尋找範圍就是 JVM 預設路徑加上Classpath, 類具體是使用哪個類載入器不確定。 4.類載入主要步驟
  • 載入 把 class 檔案的二進位制位元組流載入到 jvm 裡面
  • 驗證 確保 class 檔案的位元組流包含的資訊符合當前 jvm 的要求 有檔案格式驗證, 元資料驗證, 位元組碼驗證, 符號引用驗證等
  • 準備 正式為類變數分配記憶體並設定類變數初始值的階段, 初始化為各資料型別的零值
  • 解析 把常量值內的符號引用替換為直接引用的過程
  • 初始化 執行類構造器<clinit>()方法
  • 使用 根據相應的業務邏輯程式碼使用該類
  • 解除安裝 類從方法區移除
5.雙親委派模型: 除了頂層的啟動類載入器之外, 其餘的類載入器都應當有自己的父類載入器, 父子關係這兒一般都是以組合來實現。 工作過程: 如果一個類載入器收到了類載入的請求, 它首先不會自己去嘗試載入這個類, 而是把這個請求委派給父類載入器去完成, 最終所有的載入請求都會傳送到頂層的啟動類載入器中, 只有當父類載入器反饋自己無法完成這個請求時候, 才由子載入器來載入。 例如類Object,它放在rt.jar中,無論哪一個類載入器要載入這個類,最終都是委派給啟動類載入器進行載入,因此Object類在程式的各種類載入器環境中都是同一個類。 對於任何一個類, 都需要由載入它的類載入器和這個類本身一同確定其在 java 虛擬機器中的唯一性。 ClassLoader.loadClass()的程式碼如下,先檢查是否已經被載入過,如果沒有則parent.loadClass()呼叫父載入器的loadClass()方法,如果父載入器為空則預設使用啟動類載入器作為父載入器。如果父類載入器載入失敗,丟擲ClassNotFoundException,再呼叫自己的findClass()方法進行載入。 另外,如果我們自己實現類載入器,一般是Override複寫 findClass方法,而不是loadClass方法。
1.雙親委派模型 Java虛擬機器類載入過程是把Class類檔案載入到記憶體,並對Class檔案中的資料進行校驗、轉換解析和初始化,最終形成可以被虛擬機器直接使用的java型別的過程。 在載入階段,java虛擬機器需要完成以下3件事: a.通過一個類的全限定名來獲取定義此類的二進位制位元組流。 b.將定義類的二進位制位元組流所代表的靜態儲存結構轉換為方法區的執行時資料結構。 c.在java堆中生成一個代表該類的java.lang.Class物件,作為方法區資料的訪問入口。
(1).BootStrap ClassLoader:啟動類載入器,負責載入存放在%JAVA_HOME%\lib目錄中的,或者通被-Xbootclasspath引數所指定的路 徑中的,並且被java虛擬機器識別的(僅按照檔名識別,如rt.jar,名字不符合的類庫,即使放在指定路徑中也不會被載入)類庫到虛擬機器的記憶體中,啟 動類載入器無法被java程式直接引用。 (2).Extension ClassLoader:擴充套件類載入器,由sun.misc.Launcher$ExtClassLoader實現,負責加 載%JAVA_HOME%\lib\ext目錄中的,或者被java.ext.dirs系統變數所指定的路徑中的所有類庫,開發者可以直接使用擴充套件類載入 器。 (3).Application ClassLoader:應用程式類載入器,由sun.misc.Launcher$AppClassLoader實現,負責載入使用者類路徑 classpath上所指定的類庫,是類載入器ClassLoader中的getSystemClassLoader()方法的返回值,開發者可以直接使 用應用程式類載入器,如果程式中沒有自定義過類載入器,該載入器就是程式中預設的類載入器。 java虛擬機器規範推薦開發者使用雙親委派模式(ParentsDelegation Model)進行類載入,其載入過程如下: (1).如果一個類載入器收到了類載入請求,它首先不會自己去嘗試載入這個類,而是把類載入請求委派給父類載入器去完成。 (2).每一層的類載入器都把類載入請求委派給父類載入器,直到所有的類載入請求都應該傳遞給頂層的啟動類載入器。 (3).如果頂層的啟動類載入器無法完成載入請求,子類載入器嘗試去載入,如果連最初發起類載入請求的類載入器也無法完成載入請求時,將會丟擲ClassNotFoundException,而不再呼叫其子類載入器去進行類載入。 具體參看《深入理解Java虛擬機器》第七章 虛擬機器類載入機制。 2.單源最短路演算法簡述  Dijkstra演算法是解單源最短路徑問題的貪心演算法。 演算法流程: (a) 初始化:用起點v到該頂點w的直接邊(弧)初始化最短路徑,否則設為∞; (b) 從未求得最短路徑的終點中選擇路徑長度最小的終點u:即求得v到u的最短路徑; (c) 修改最短路徑:計算u的鄰接點的最短路徑,若(v,…,u)+(u,w)<(v,…,w),則以(v,…,u,w)代替。 (d) 重複(b)-(c),直到求得v到其餘所有頂點的最短路徑。 演算法基於:如果存在一條從i到j的最短路徑(Vi.....Vk,Vj),Vk是Vj前面的一頂點。那麼(Vi...Vk)也必定是從i到k的最短路徑。 dist[j]=min{dist[j],dist[i]+matrix[i][j]} 單源最短路除了dijkstra演算法之外,還有一種常用的演算法叫做SPFA(shortest path faster algorithm)演算法,不同於dijkstra的複雜度為o(n^2),SPFA演算法的平均複雜度為o(kE),E為邊數,且k通常不超過2。用bfs實現。 SPFA的核心思想如下: 最開始起點入隊,然後考慮和起點相鄰的點,更新dis陣列,並將這些點入隊; 當佇列不為空時,每次取隊首一個點,對這個點相鄰的點進行鬆弛操作,即比較原先的dis和經過新加入的點的優化後的dis,如果鬆弛成功,且被鬆弛的點不在佇列中,則將其加入佇列,重複上述動作。 SPFA可以用來判斷負環,我們開一個cnt陣列記錄每個點入隊的次數,如果次數超過n說明出現負環。 3..有若干個點,給出哪些點是相連的,求第一個點到最後一個點是否聯通,並求出經過幾個點(實際還是最短路問題) 4.Mybatis和hibernate有什麼區別 Hibernate和Mybatis都是orm物件關係對映框架,都是用於將資料持久化的框架技術。 Hiberante較深度的封裝了jdbc,對開發者寫sql的能力要求的不是那麼的高,我們只要通過hql語句操作物件即可完成對資料持久化的操作了。 另外hibernate可移植性好,如一個專案開始使用的是mysql資料庫,但是隨著業務的發展,現mysql資料庫已經無法滿足當前的繡球了,現在決定使用Oracle資料庫,雖然sql標準定義的資料庫間的sql語句差距不大,但是不同的資料庫sql標準還是有差距的,那麼我們手動修改起來會存在很大的困難,使用hibernate只需改變一下資料庫方言即可搞定。用hibernate框架,資料庫的移植變的非常方便。 但是hibernate也存在著諸多的不足,比如在實際開發過程中會生成很多不必要的sql語句耗費程式資源,優化起來也不是很方便,且對儲存過程支援的也不夠強大。但是針對於hibernate它也提供了一些優化策略,比如說懶載入、快取、策略模式等都是針對於它的優化方案。 Mybatis 也是對jdbc的封裝,但是封裝的沒有hibernate那麼深,我們可以再配置檔案中寫sql語句,可以根據需求定製sql語句,資料優化起來較hibernate容易很多。 Mybatis要求程式設計師寫sql的能力要相對使用hibernate的開發人員要高的多,且可移植性也不是很好。 涉及到大資料的系統使用Mybatis比較好,因為優化較方便。涉及的資料量不是很大且對優化沒有那麼高,可以使用hibernate。 兩者相同點
  • Hibernate與MyBatis都可以是通過SessionFactoryBuider由XML配置檔案生成SessionFactory,然後由SessionFactory 生成Session,最後由Session來開啟執行事務和SQL語句。其中SessionFactoryBuider,SessionFactory,Session的生命週期都是差不多的。
  • Hibernate和MyBatis都支援JDBC和JTA事務處理。
Mybatis優勢
  • MyBatis可以進行更為細緻的SQL優化,可以減少查詢欄位。
  • MyBatis容易掌握,而Hibernate門檻較高。
Hibernate優勢
  • Hibernate的DAO層開發比MyBatis簡單,Mybatis需要維護SQL和結果對映。
  • Hibernate對物件的維護和快取要比MyBatis好,對增刪改查的物件的維護要方便。
  • Hibernate資料庫移植性很好,MyBatis的資料庫移植性不好,不同的資料庫需要寫不同SQL。
  • Hibernate有更好的二級快取機制,可以使用第三方快取。MyBatis本身提供的快取機制不佳。
他人總結
  • Hibernate功能強大,資料庫無關性好,O/R對映能力強,如果你對Hibernate相當精通,而且對Hibernate進行了適當的封裝,那麼你的專案整個持久層程式碼會相當簡單,需要寫的程式碼很少,開發速度很快,非常爽。 
  • Hibernate的缺點就是學習門檻不低,要精通門檻更高,而且怎麼設計O/R對映,在效能和物件模型之間如何權衡取得平衡,以及怎樣用好Hibernate方面需要你的經驗和能力都很強才行。 
  • iBATIS入門簡單,即學即用,提供了資料庫查詢的自動物件繫結功能,而且延續了很好的SQL使用經驗,對於沒有那麼高的物件模型要求的專案來說,相當完美。 
  • iBATIS的缺點就是框架還是比較簡陋,功能尚有缺失,雖然簡化了資料繫結程式碼,但是整個底層資料庫查詢實際還是要自己寫的,工作量也比較大,而且不太容易適應快速資料庫修改。
針對高階查詢,Mybatis需要手動編寫SQL語句,以及ResultMap。而Hibernate有良好的對映機制,開發者無需關心SQL的生成與結果對映,可以更專注於業務流程。 5.資料庫索引優點和缺點?sql優化方案(見資料庫總結) 6.滑動視窗演算法 7.簡單介紹下執行緒池的引數?你瞭解哪些執行緒池 (參看7.執行緒池的配置) 8.簡述JVM,從類載入一直到執行時的記憶體區域 9.Mybatis原理 MyBatis 是支援定製化 SQL、儲存過程以及高階對映的優秀的持久層框架。MyBatis 避免了幾乎所有的 JDBC 程式碼和手工設定引數以及抽取結果集。 MyBatis 使用簡單的 XML 或註解來配置和對映基本體,將介面和 Java 的 POJOs(Plain Old Java Objects, 普通的 Java物件)對映成資料庫中的記錄。   MyBatis應用程式根據XML配置檔案建立 SqlSessionFactory,SqlSessionFactory在根據配置,配置來源於兩個地方,一處是配置檔案,一處是Java程式碼的註解, 獲取一個SqlSession。SqlSession包含了執行sql所需要的所有方法,可以通過SqlSession例項直接執行對映的sql語句,完成對資料的增刪改查和事務提交等,用完之後關閉SqlSession。 通過factory方法獲取sqlsession----通過MapperProxy代理到dao--執行底層資料庫操作 10.說下CMS收集器,說下G1收集器(之前有總結了) ----------------------------------------------------蘑菇街--------------------------------------- 1.Mysql和mongodb索引原理(說一下B+tree和B-tree區別,為什麼一個用b+一個用b-,為什麼索引用btree不用平衡二叉樹)mysql兩種儲存引擎 B-樹和B+樹最重要的一個區別就是B+樹只有葉節點存放資料,其餘節點用來索引,而B-樹是每個索引節點都會有Data域。 這就決定了B+樹更適合用來儲存外部資料,也就是所謂的磁碟資料。 從Mysql(Inoodb)的角度來看,B+樹是用來充當索引的,一般來說索引非常大,尤其是關係性資料庫這種資料量大的索引能達到億級別,所以為了減少記憶體的佔用,索引也會被儲存在磁碟上。 那麼Mysql如何衡量查詢效率呢?磁碟IO次數,B-樹(B類樹)的特定就是每層節點數目非常多,層數很少,目的就是為了就少磁碟IO次數,當查詢資料的時候,最好的情況就是很快找到目標索引,然後讀取資料,使用B+樹就能很好的完成這個目的,但是B-樹的每個節點都有data域(指標),這無疑增大了節點大小,說白了增加了磁碟IO次數(磁碟IO一次讀出的資料量大小是固定的,單個數據變大,每次讀出的就少,IO次數增多,一次IO多耗時啊!),而B+樹除了葉子節點其它節點並不儲存資料,節點小,磁碟IO次數就少。這是優點之一。 另一個優點是什麼,B+樹所有的Data域在葉子節點,一般來說都會進行一個優化,就是將所有的葉子節點用指標串起來。這樣遍歷葉子節點就能獲得全部資料,這樣就能進行區間訪問啦。 至於MongoDB為什麼使用B-樹而不是B+樹,可以從它的設計角度來考慮,它並不是傳統的關係性資料庫,而是以Json格式作為儲存的nosql,目的就是高效能,高可用,易擴充套件。首先它擺脫了關係模型,上面所述的優點2需求就沒那麼強烈了,其次Mysql由於使用B+樹,資料都在葉節點上,每次查詢都需要訪問到葉節點,而MongoDB使用B-樹,所有節點都有Data域,只要找到指定索引就可以進行訪問,無疑單次查詢平均快於Mysql(但側面來看Mysql至少平均查詢耗時差不多)。 總體來說,Mysql選用B+樹和MongoDB選用B-樹還是以自己的需求來選擇的。 2.浮點型為什麼不是精確值 十進位制小數部分化二進位制,常常化不盡。 如同無限迴圈小數,最後有截斷誤差。 二進位制無法精確表示十進位制的十分之一。 使用BigDecimal來做精確運算 3.執行緒池原理,單核作業系統是否應該使用多執行緒,為什麼 應該,不知道為什麼。。。 4.有1萬個左右的髒詞,每次發帖要判斷帖子裡邊是否包括有髒詞,資料庫應該如何設計 可以建立一個髒詞字典表,寫好函式判斷帖子正文裡面是否有髒詞。然後再這個帖子正文欄位上面建立check 約束。