1. 程式人生 > >總結了一些新的面試題,包含答案(持續更新中)

總結了一些新的面試題,包含答案(持續更新中)

Java根底
● 集合類以及集合框架;HashMap與HashTable完成原理,執行緒平安性,hash抵觸及處置演算法;ConcurrentHashMap;
- Collection 集合的根介面
+Set 繼承類,不能包含重複元素,無序
+List 繼承類,可以包含重複元素,按索引訪問,有序
- Map 和Colletion互相獨立
-Iterator 被所有的集合類實現
+hasNext()是否有下個元素
+next()返回下個元素
+remove()
 在類集中提供了以下四種的常見輸出方式:
1)Iterator:迭代輸出,是使用最多的輸出方式。
2)ListIterator:是Iterator的子介面,專門用於輸出List中的內容。
3)foreach輸出:JDK1.5之後提供的新功能,可以輸出陣列或集合。
4)for迴圈
- ArrayList和LinkedList
ArrayList和LinkedList在用法上沒有區別,但是在功能上還是有區別的。LinkedList經常用在增刪操作較多而查詢操作很少的情況下,ArrayList則相反。
為什麼ArrayList查詢速度快?
因為ArrayList底層使用的是陣列。而LinkList使用的是連結串列,查詢的時候會從頭開始查。相反,插入和刪除使用LinkList速度比較快,因為而在LinkedList的中間插入或刪除一個元素的開銷是固定的。
Map集合
實現類:HashMap、Hashtable、LinkedHashMap和TreeMap
HashMap 
HashMap是最常用的Map,它根據鍵的HashCode值儲存資料,根據鍵可以直接獲取它的值,具有很快的訪問速度,遍歷時,取得資料的順序是完全隨機的。因為鍵物件不可以重複,所以HashMap最多隻允許一條記錄的鍵為Null,允許多條記錄的值為Null,是非同步的。如果長度超過75%,長度增加一倍。
Hashtable
Hashtable與HashMap類似,是HashMap的執行緒安全版,它支援執行緒的同步,即任一時刻只有一個執行緒能寫Hashtable,因此也導致了Hashtale在寫入時會比較慢,它繼承自Dictionary類,不同的是它不允許記錄的鍵或者值為null,同時效率較低。
ConcurrentHashMap
執行緒安全,並且鎖分離。ConcurrentHashMap內部使用段(Segment)來表示這些不同的部分,每個段其實就是一個小的hash table,它們有自己的鎖。只要多個修改操作發生在不同的段上,它們就可以併發進行。
Hashtable和ConcurrentHashMap有什麼分別呢?
它們都可以用於多執行緒的環境,但是當Hashtable的大小增加到一定的時候,效能會急劇下降,因為迭代時需要被鎖定很長的時間。因為ConcurrentHashMap引入了分割(segmentation),不論它變得多麼大,僅僅需要鎖定map的某個部分,而其它的執行緒不需要等到迭代完成才能訪問map。簡而言之,在迭代的過程中,ConcurrentHashMap僅僅鎖定map的某個部分,而Hashtable則會鎖定整個map。
ConcurrentHashMap能完全替代HashTable嗎?
hash table雖然效能上不如ConcurrentHashMap,但並不能完全被取代,兩者的迭代器的一致性不同的,hash table的迭代器是強一致性的,而concurrenthashmap是弱一致的。 ConcurrentHashMap的get,clear,iterator 都是弱一致性的。 Doug Lea 也將這個判斷留給使用者自己決定是否使用ConcurrentHashMap。
LinkedHashMap
LinkedHashMap儲存了記錄的插入順序,在用Iteraor遍歷LinkedHashMap時,先得到的記錄肯定是先插入的,在遍歷的時候會比HashMap慢,有HashMap的全部特性。輸出的順序和輸入的相同.
TreeMap
TreeMap實現SortMap介面,能夠把它儲存的記錄根據鍵排序,預設是按鍵值的升序排序(自然順序),也可以指定排序的比較器,當用Iterator遍歷TreeMap時,得到的記錄是排過序的。不允許key值為空,非同步的;按自然順序或自定義順序遍歷鍵.
Map的遍歷有兩種:
KeySet()
entrySet()
推薦使用第二種方式,即entrySet()方法,效率較高
Vector和ArrayList
1,vector是執行緒同步的,所以它也是執行緒安全的,而arraylist是執行緒非同步的,是不安全的。如果不考慮到執行緒的安全因素,一般用arraylist效率比較高。
2,如果集合中的元素的數目大於目前集合陣列的長度時,vector增長率為目前陣列長度的100%,而arraylist增長率為目前陣列長度的50%。如果在集合中使用資料量比較大的資料,用vector有一定的優勢。
3,如果查詢一個指定位置的資料,vector和arraylist使用的時間是相同的,如果頻繁的訪問資料,這個時候使用vector和arraylist都可以。而如果移動一個指定位置會導致後面的元素都發生移動,這個時候就應該考慮到使用linklist,因為它移動一個指定位置的資料時其它元素不移動。
ArrayList 和Vector是採用陣列方式儲存資料,此陣列元素數大於實際儲存的資料以便增加和插入元素,都允許直接序號索引元素,但是插入資料要涉及到陣列元素移動等記憶體操作,所以索引資料快,插入資料慢,Vector由於使用了synchronized方法(執行緒安全)所以效能上比ArrayList要差,LinkedList使用雙向連結串列實現儲存,按序號索引資料需要進行向前或向後遍歷,但是插入資料時只需要記錄本項的前後項即可,所以插入數度較快。
arraylist和linkedlist
1.ArrayList是實現了基於動態陣列的資料結構,LinkedList基於連結串列的資料結構。
2.對於隨機訪問get和set,ArrayList覺得優於LinkedList,因為LinkedList要移動指標。
3.對於新增和刪除操作add和remove,LinedList比較佔優勢,因為ArrayList要移動資料。 這一點要看實際情況的。若只對單條資料插入或刪除,ArrayList的速度反而優於LinkedList。但若是批量隨機的插入刪除資料,LinkedList的速度大大優於ArrayList. 因為ArrayList每插入一條資料,要移動插入點及之後的所有資料。
HashMap與TreeMap
1、 HashMap通過hashcode對其內容進行快速查詢,而TreeMap中所有的元素都保持著某種固定的順序,如果你需要得到一個有序的結果你就應該使用TreeMap(HashMap中元素的排列順序是不固定的)。
2、在Map 中插入、刪除和定位元素,HashMap是最好的選擇。但如果您要按自然順序或自定義順序遍歷鍵,那麼TreeMap會更好。使用HashMap要求新增的鍵類明確定義了hashCode()和 equals()的實現。
兩個map中的元素一樣,但順序不一樣,導致hashCode()不一樣。
同樣做測試:
在HashMap中,同樣的值的map,順序不同,equals時,false;
而在treeMap中,同樣的值的map,順序不同,equals時,true,說明,treeMap在equals()時是整理了順序了的。
HashTable與HashMap
1、同步性:Hashtable是執行緒安全的,也就是說是同步的,而HashMap是執行緒序不安全的,不是同步的。
2、HashMap允許存在一個為null的key,多個為null的value 。
3、hashtable的key和value都不允許為null。
HashMap和陣列誰更快?
HashMap底層是一個數組+連結串列實現。其基本原理是:定義一個LinkedList的陣列,然後將資料儲存到這個連結串列陣列內.
中間要通過陣列找到連結串列,然後再去除value。所以應該是陣列要快。
網上我也查過有人做了實驗,也是同樣的結果。
介紹幾個排序演算法?
氣泡排序
比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。在這一點,最後的元素應該會是最大的數。
針對所有的元素重複以上的步驟,除了最後一個。
持續每次對越來越少的元素重複上面的步驟,直到沒有任何一對數字需要比較。
快速排序
從後往前比較,用基準值和最後一個值比較,如果比基準值小的交換位置,如果沒有繼續比較下一個,直到找到第一個比基準值小的值才交換。找到這個值之後,又從前往後開始比較,如果有比基準值大的,交換位置,如果沒有繼續比較下一個,直到找到第一個比基準值大的值才交換。直到從前往後的比較索引>從後往前比較的索引,結束第一次迴圈,此時,對於基準值來說,左右兩邊就是有序的了。
效率最好:三數取中(median-of-three)+插排+聚集相等元素。能減少迭代次數執行緒和程序各自有什麼區別和優劣呢?
程序是資源分配的最小單位,執行緒是程式執行的最小單位。
程序有自己的獨立地址空間,每啟動一個程序,系統就會為它分配地址空間,建立資料表來維護程式碼段、堆疊段和資料段,這種操作非常昂貴。而執行緒是共享程序中的資料的,使用相同的地址空間,因此CPU切換一個執行緒的花費遠比程序要小很多,同時建立一個執行緒的開銷也比程序要小很多。
執行緒之間的通訊更方便,同一程序下的執行緒共享全域性變數、靜態變數等資料,而程序之間的通訊需要以通訊的方式(IPC)進行。不過如何處理好同步與互斥是編寫多執行緒程式的難點。
但是多程序程式更健壯,多執行緒程式只要有一個執行緒死掉,整個程序也死掉了,而一個程序死掉並不會對另外一個程序造成影響,因為程序有自己獨立的地址空間。
● Java的併發、多執行緒、 執行緒模型;
常用的多執行緒設計模式包括:Future模式、Master-Worker模式、Guarded Suspeionsion模式、不變模式和生產者-消費者模式等。
● 中綴表示式(中綴記法)
中綴表示式是一種通用的算術或邏輯公式表示方法,操作符以中綴形式處於運算元的中間。中綴表示式是人們常用的算術表示方法。
雖然人的大腦很容易理解與分析中綴表示式,但對計算機來說中綴表示式卻是很複雜的,因此計算表示式的值時,通常需要先將中綴表示式轉換為字首或字尾表示式,然後再進行求值。對計算機來說,計算字首或字尾表示式的值非常簡單。
綴表示式的計算機求值:
與字首表示式類似,只是順序是從左至右:
從左至右掃描表示式,遇到數字時,將數字壓入堆疊,遇到運算子時,彈出棧頂的兩個數,用運算子對它們做相應的計算(次頂元素 op 棧頂元素),並將結果入棧;重複上述過程直到表示式最右端,最後運算得出的值即為表示式的結果。
例如字尾表示式“3 4 + 5 × 6 -”:
(1) 從左至右掃描,將3和4壓入堆疊;
(2) 遇到+運算子,因此彈出4和3(4為棧頂元素,3為次頂元素,注意與字首表示式做比較),計算出3+4的值,得7,再將7入棧;
(3) 將5入棧;
(4) 接下來是×運算子,因此彈出5和7,計算出7×5=35,將35入棧;
(5) 將6入棧;
(6) 最後是-運算子,計算出35-6的值,即29,由此得出最終結果。
將中綴表示式轉換為字尾表示式:
與轉換為字首表示式相似,遵循以下步驟:
(1) 初始化兩個棧:運算子棧S1和儲存中間結果的棧S2;
(2) 從左至右掃描中綴表示式;
(3) 遇到運算元時,將其壓入S2;
(4) 遇到運算子時,比較其與S1棧頂運算子的優先順序:
(4-1) 如果S1為空,或棧頂運算子為左括號“(”,則直接將此運算子入棧;
(4-2) 否則,若優先順序比棧頂運算子的高,也將運算子壓入S1(注意轉換為字首表示式時是優先順序較高或相同,而這裡則不包括相同的情況);
(4-3) 否則,將S1棧頂的運算子彈出並壓入到S2中,再次轉到(4-1)與S1中新的棧頂運算子相比較;
(5) 遇到括號時:
(5-1) 如果是左括號“(”,則直接壓入S1;
(5-2) 如果是右括號“)”,則依次彈出S1棧頂的運算子,並壓入S2,直到遇到左括號為止,此時將這一對括號丟棄;
(6) 重複步驟(2)至(5),直到表示式的最右邊;
(7) 將S1中剩餘的運算子依次彈出並壓入S2;
(8) 依次彈出S2中的元素並輸出,結果的逆序即為中綴表示式對應的字尾表示式(轉換為字首表示式時不用逆序)。
一、future 模式
Future 模式採用非同步呼叫,充分利用等待的時間段,執行其他業務邏輯處理,最後再執行返回較慢的Future 資料,從而提高系統的響應速度
Master-Worker模式是常用的並行模式之一,它的核心思想是:系統由兩類程序協同工作,即Master程序和Worker程序,Master負責接收和分配任務,Wroker負責處理子任務。當各個Worker程序將子任務處理完成後,將結果返回給Master程序,由Master程序進行彙總,從而得到最終的結果
二、JDK1.6的內建Future實現
多執行緒的代價:
設計更復雜
上下文切換的開銷
增加資源消耗
死鎖:
死鎖是兩個或更多執行緒阻塞著等待其它處於死鎖狀態的執行緒所持有的鎖。死鎖通常發生在多個執行緒同時但以不同的順序請求同一組鎖的時候。
例如,如果執行緒1鎖住了A,然後嘗試對B進行加鎖,同時執行緒2已經鎖住了B,接著嘗試對A進行加鎖,這時死鎖就發生了。執行緒1永遠得不到B,執行緒2也永遠得不到A,並且它們永遠也不會知道發生了這樣的事情。為了得到彼此的物件(A和B),它們將永遠阻塞下去。這種情況就是一個死鎖。 資料庫的死鎖更加複雜的死鎖場景發生在資料庫事務中。一個數據庫事務可能由多條SQL更新請求組成。當在一個事務中更新一條記錄,這條記錄就會被鎖住避免其他事務的更新請求,直到第一個事務結束。同一個事務中每一個更新請求都可能會鎖住一些記錄當多個事務同時需要對一些相同的記錄做更新操作時,就很有可能發生死鎖● 什麼是執行緒池,如何運用? 答:執行緒池就是事前將多個執行緒物件放到一個容器中,當運用的時分就不必new 執行緒而是間接去池中拿執行緒即可● 資料分歧性如何保證;Synchronized關鍵字,類鎖,辦法鎖,重入鎖;

對於類鎖,則會把整個類鎖住,也就說只能有一個物件擁有當前類的鎖。當一個物件擁有了類鎖之後,另外一個物件還想競爭鎖的話則會被阻塞。兩個物件A,B,如果A正在訪問一個被類鎖修飾的方法function,那麼B則不能訪問。因為類鎖只能在同一時刻被一個物件擁有。相對於物件鎖,則是不同。還是A,B兩個物件,如果A正在訪問物件鎖修飾的function,那麼這個時候B也可以同時訪問。對於物件鎖,當一個物件擁有鎖之後,訪問一個加了物件鎖的方法,而該方法中又呼叫了該類中其他加了物件鎖的方法,那麼這個時候是不會阻塞住的。這是java通過可重入鎖機制實現的。可重入鎖指的是當一個物件擁有物件鎖之後,可以重複獲取該鎖。因為synchronized塊是可重入的,所以當你訪問一個物件鎖的方法的時候,在該方法中繼續訪問其他物件鎖方法是不會被阻塞的。可重入鎖,也叫做遞迴鎖,指的是同一執行緒 外層函式獲得鎖之後 ,內層遞迴函式仍然有獲取該鎖的程式碼,但不受影響。

● Java中完成多型的機制是什麼;1 過載:有同樣的方法名稱不同的引數列表。a(){} a(String b){}...2 重寫(也稱覆蓋):即可以重新編寫與父類同名方法形象的稱之為重寫(覆蓋)。● 如何將一個Java物件序列化到檔案裡;

使用ObjectOutputStream和ObjectInputStream來進行物件的讀取;使用ObjectOutputStream物件的writeObject()方法來進行物件的寫入;

使用ObjectInputStream物件的readObject()方法來讀取物件

● 說說你對Java反射的瞭解; 答:Java 中的反射首先是可以獲取到Java 中要反射類的位元組碼, 獲取位元組碼有三種辦法

方式一,使用類的class屬性:Class<java.util.Date> clz1 = java.util.Date.class;

方式二,通過Class類中的靜態方法forName(String className),傳入類的全限定名(必須新增完整包名)Class<?> clz2 = Class.forName(“java.util.Date”);

方式三,通過物件的getClass方法來實現,其中,getClass()Object類中的方法,所有的物件都可以呼叫該方法java.util.Date str = new java.util.Date();

Class<?> clz3 = str.getClass()

;● 在Java中wait和seelp辦法的不同;

答:最大的不同是在等候時wait 會釋放鎖,而sleep 不斷持有鎖。wait 通常被用於執行緒間互動,sleep 通常被用於暫停執行。

● ThreadLocal原理,完成及如何保證Local屬性;在同步機制中,通過物件的鎖機制保證同一時間只有一個執行緒訪問變數。這時該變數是多個執行緒共享的,使用同步機制要求程式慎密地分析什麼時候對變數進行讀寫,什麼時候需要鎖定某個物件,什麼時候釋放物件鎖等繁雜的問題,程式設計和編寫難度相對較大。  而ThreadLocal則從另一個角度來解決多執行緒的併發訪問。ThreadLocal會為每一個執行緒提供一個獨立的變數副本,從而隔離了多個執行緒對資料的訪問衝突。因為每一個執行緒都擁有自己的變數副本,從而也就沒有必要對該變數進行同步了。ThreadLocal提供了執行緒安全的共享物件,在編寫多執行緒程式碼時,可以把不安全的變數封裝進ThreadLocal。和鎖的區別:一個是鎖機制進行時間換空間,一個是儲存拷貝進行空間換時間工作中用途:日誌記錄使用了攔截器,所以需要在攔截器中訪問到需要記錄的值。我把要記錄的值放在ThreadLocal中。。

● String StringBuilder StringBuffer比照;1.如果要操作少量的資料用 = String 字串常量2.單執行緒操作字串緩衝區 下操作大量資料 = StringBuilder 字串變數3.多執行緒操作字串緩衝區 下操作大量資料 = StringBuffer 字串變數● 你所曉得的設計形式有哪些; 答:Java 中普通以為有23 種設計形式創立型形式,共五種:工廠辦法形式、籠統工廠形式、單例形式、建造者形式、原型形式。構造型形式,共七種:介面卡形式、裝飾器形式、代理形式、外觀形式、橋接形式、組合形式、享元形式。行為型形式,共十一種:戰略形式、模板辦法形式、察看者形式、迭代子形式、責任鍊形式、命令形式、備忘錄形式、形態形式、拜訪者形式、中介者形式、直譯器形式。Java如何呼叫c、c++言語JNI就是一個允許Java語言和其他程式語言(主要是C/C++)通訊的介面。C/C++是系統級的程式語言, 可以用來開發任何和系統相關的程式和類庫, 但是Java本身編寫底層的應用比較難實現, 使用JNI可以呼叫現有的本地庫, 極大地靈活了Java的開發. C/C++的效率是目前最好的語言, 可以使用C/C++來實現一些實時性非常高的部分. C/C++和Java本身都是非常流行的程式語言, 一些大型軟體中經常使用語言之間的混合程式設計。一旦使用JNI, JAVA程式就喪失了JAVA平臺的兩個優點: 程式不在跨平臺。要想跨平臺,必須在不同的系統環境中重新編譯本地語言部分;程式不再是絕對安全的,原生代碼的不當使用可能導致整個陳旭崩潰。一個通用的規則是,你應該讓本地方法集中在少數幾個類當中,這樣就降低了Java語言和C/C++之間的耦合性。使用JNI實現Java與C語言混合程式設計的基本步驟如下:編寫帶有native宣告的方法的java類使用javac命令編譯所有的java類然後使用javah + 類名生成副檔名為.h的標頭檔案使用C/C++實現本地方法

將C/C++編寫的檔案生成動態連結庫

● 介面與回撥;回撥的原理;寫一個回撥demo;有一天小王遇到一個很難的問題,問題是“1 + 1 = ?”,就打電話問小李,小李一下子也不知道,就跟小王說,等我辦完手上的事情,就去想想答案,小王也不會傻傻的拿著電話去等小李的答案吧,於是小王就對小李說,我還要去逛街,你知道了答案就打我電話告訴我,於是掛了電話,自己辦自己的事情,過了一個小時,小李打了小王的電話,告訴他答案是2。使用非同步執行緒實現● 泛型原理,舉例闡明;解析與分派;泛型是Java 1.5的新特性,泛型的本質是引數化型別,也就是說所操作的資料型別被指定為一個引數。這種引數型別可以用在類、介面和方法的建立中,分別稱為泛型類、泛型介面、泛型方法。泛型在使用中還有一些規則和限制: 1、泛型的型別引數只能是類型別(包括自定義類),不能是簡單型別。2、同一種泛型可以對應多個版本(因為引數型別是不確定的),不同版本的泛型類例項是不相容的。3、泛型的型別引數可以有多個。4、泛型的引數型別可以使用extends語句,例如。習慣上成為“有界型別”。5、泛型的引數型別還可以是萬用字元型別● 抽象類與介面的區別;使用場景;抽象類能否可以沒無方法和屬性(可以);1) 在抽象類中可以寫非抽象的方法,從而避免在子類中重複書寫他們,這樣可以提高程式碼的複用性,這是抽象類的優勢;介面中只能有抽象的方法。2) 一個類只能繼承一個直接父類,這個父類可以是具體的類也可是抽象類;但是一個類可以實現多個介面。介面是對動作的抽象,而抽象類是對根源的抽象抽象類主要是用來抽象類別,介面主要是用來抽象方法功能。當你關注事物的本質的時候,請用抽象類;當你關注一種操作的時候,用介面。抽象類的功能應該要遠多於介面,但是定義抽象類的代價較高。因為高階語言一個類只能繼承一個父類,即你在設計這個類的時候必須要抽象出所有這個類的子類所具有的共同屬性和方法;但是類(介面)卻可以繼承多個介面,因此每個介面你只需要將特定的動作方法抽象到這個介面即可。也就是說,介面的設計具有更大的可擴充套件性,而抽象類的設計必須十分謹慎。● 靜態屬性和靜態辦法能否可以被承繼?能否可以被重寫java中靜態屬性和和靜態方法可以被繼承,但是沒有被重寫(overwrite)而是被隱藏重寫的功能是:“重寫”後子類的優先順序要高於父類的優先順序,但是“隱藏”是沒有這個優先順序之分的。● Java的異常體系;● 如何控制某個辦法允許併發訪問執行緒的個數;Semaphore semaphore = new Semaphore(5,true);semaphore.acquire();建構函式建立了一個 Semaphore 物件,並且初始化了 5 個訊號。這樣的效果是控制元件 test 方法最多隻能有 5 個執行緒併發訪問,對於 5 個執行緒時就排隊等待,走一個來一下;● 靜態代理和動態代理的區別,什麼場景運用;一般來說,動態代理用的場合比較多,比如spring的事務管理、AOP等都是動態代理。代理模式可以在不更改原始類的情況下實現額外的處理工作,比如日誌、引數修改等,也就是我們常聽到的AOP概念了,用好了代理模式其實是可以為我們做很多事情的。● jvm運轉時資料區域有哪幾區域性組成,各自作用 ; 執行緒共享區:堆可能出現的異常實現堆可以是固定大小的,也可以通過設定配置檔案設定該為可擴充套件的。如果堆上沒有記憶體進行分配,並無法進行擴充套件時,將會丟擲OutOfMemoryError異常。當方法區無法滿足記憶體分配需求時,將丟擲OutOfMemoryError異常。執行緒獨佔區:棧可能出現的異常如果執行緒請求的棧深度大於虛擬機器所允許的深度,將丟擲StackOverflowError異常。 如果在動態擴充套件記憶體的時候無法申請到足夠的記憶體,就會丟擲OutOfMemoryError異常。● gc演算法有哪些 ; gc蒐集器有哪些 ;1、引用計數(reference counting)2、複製(copying)3、標記-清掃(Mark-and-sweep)4、標記-壓縮(Mark-Compact)5、分代(generational collecting)導致Gc的情況:1、tenured被寫滿2、perm被寫滿3、System.gc()的顯式呼叫。4、上一次GC之後heap的各域分配策略動態變化。● 簡述class載入各階段程序 ; class ; loader有哪些模型 ;● 簡述常用的JDK命令列工具 ;● 簡述位元組碼檔案組成 ;● 講講你往常是如何針對詳細的SQL做優化 ;● mysql的儲存引擎有哪些,區別 ;● gc:記憶體模型;● gc: 渣滓回收 ;● 多執行緒:如何完成一個定時排程和迴圈排程的工具類。但提交義務處置不過去的時分,回絕機制應該如何處置 ; 執行緒池默許有哪幾種回絕機制 ;● 多執行緒: 如何完成一個ThreadLocal ;● 說說你理解的一個執行緒平安佇列 ;● Atomic包的完成原理是什麼 ;● CAS又是怎樣保證原子性的 ;● string剖析1000次迴圈subString用了多少記憶體 ;