京東阿里Java高級面試題(List和Set比較,各自的子類比較)

List和Set比較,各自的子類比較前端

對比一: Arraylist與LinkedList的比較java

一、ArrayList是實現了基於動態數組的數據結構,由於地址連續,一旦數據存儲好了,查詢操做效率會比較高(在內存裏是連着放的)。面試

二、由於地址連續, ArrayList要移動數據,因此插入和刪除操做效率比較低。   redis

三、LinkedList基於鏈表的數據結構,地址是任意的,因此在開闢內存空間的時候不須要等一個連續的地址,對於新增和刪除操做add和remove,LinedList比較佔優點。算法

四、由於LinkedList要移動指針,因此查詢操做性能比較低。spring

適用場景分析:數據庫

當須要對數據進行對此訪問的狀況下選用ArrayList,當須要對數據進行屢次增長刪除修改時採用LinkedList。編程

對比二: ArrayList與Vector的比較後端

一、Vector的方法都是同步的,是線程安全的,而ArrayList的方法不是,因爲線程的同步必然要影響性能。所以,ArrayList的性能比Vector好。 
二、當Vector或ArrayList中的元素超過它的初始大小時,Vector會將它的容量翻倍,而ArrayList只增長50%的大小,這樣。ArrayList就有利於節約內存空間。數組

三、大多數狀況不使用Vector,由於性能很差,可是它支持線程的同步,即某一時刻只有一個線程可以寫Vector,避免多線程同時寫而引發的不一致性。

四、Vector能夠設置增加因子,而ArrayList不能夠。

適用場景分析:

一、Vector是線程同步的,因此它也是線程安全的,而ArrayList是線程異步的,是不安全的。若是不考慮到線程的安全因素,通常用ArrayList效率比較高。

二、若是集合中的元素的數目大於目前集合數組的長度時,在集合中使用數據量比較大的數據,用Vector有必定的優點。

對比三: HashSet與TreeSet的比較

1.TreeSet 是二叉樹實現的,Treeset中的數據是自動排好序的,不容許放入null值 。

2.HashSet 是哈希表實現的,HashSet中的數據是無序的,能夠放入null,但只能放入一個null,二者中的值都不能重複,就如數據庫中惟一約束 。

3.HashSet要求放入的對象必須實現HashCode()方法,放入的對象,是以hashcode碼做爲標識的,而具備相同內容的String對象,hashcode是同樣,因此放入的內容不能重複。可是同一個類的對象能夠放入不一樣的實例。

適用場景分析:

HashSet是基於Hash算法實現的,其性能一般都優於TreeSet。咱們一般都應該使用HashSet,在咱們須要排序的功能時,咱們才使用TreeSet。

HashMap和ConcurrentHashMap的區別

一、HashMap不是線程安全的,而ConcurrentHashMap是線程安全的。

二、ConcurrentHashMap採用鎖分段技術,將整個Hash桶進行了分段segment,也就是將這個大的數組分紅了幾個小的片斷segment,並且每一個小的片斷segment上面都有鎖存在,那麼在插入元素的時候就須要先找到應該插入到哪個片斷segment,而後再在這個片斷上面進行插入,並且這裏還須要獲取segment鎖。

三、ConcurrentHashMap讓鎖的粒度更精細一些,併發性能更好。

至於二者的底層實現,你若是想經過一篇文章就理解了,那就too young了,好好找些博文+看源碼去吧。

HashTable和ConcurrentHashMap的區別

它們均可以用於多線程的環境,可是當Hashtable的大小增長到必定的時候,性能會急劇降低,由於迭代時須要被鎖定很長的時間。由於ConcurrentHashMap引入了分割(segmentation),不論它變得多麼大,僅僅須要鎖定map的某個部分,而其它的線程不須要等到迭代完成才能訪問map。簡而言之,在迭代的過程當中,ConcurrentHashMap僅僅鎖定map的某個部分,而Hashtable則會鎖定整個map。

String,StringBuffer和StringBuilder的區別

一、運行速度,或者說是執行速度,在這方面運行速度快慢爲:StringBuilder > StringBuffer > String。

二、線程安全上,StringBuilder是線程不安全的,而StringBuffer是線程安全的。

適用場景分析:

String:適用於少許的字符串操做的狀況

StringBuilder:適用於單線程下在字符緩衝區進行大量操做的狀況

StringBuffer:適用多線程下在字符緩衝區進行大量操做的狀況

    • *

wait和sleep的區別

一、sleep()方法是屬於Thread類中的,而wait()方法,則是屬於Object類中的。

二、sleep()方法致使了程序暫停執行指定的時間,讓出cpu給其餘線程,可是他的監控狀態依然保持着,當指定的時間到了又會自動恢復運行狀態。因此在調用sleep()方法的過程當中,線程不會釋放對象鎖。

三、調用wait()方法的時候,線程會放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象調用notify()方法後本線程才進入對象鎖定池準備獲取對象鎖進入運行狀態。

JVM的內存結構

根據 JVM 規範,JVM 內存共分爲虛擬機棧、堆、方法區、程序計數器、本地方法棧五個部分。

一、Java虛擬機棧:

線程私有;每一個方法在執行的時候會建立一個棧幀,存儲了局部變量表,操做數棧,動態鏈接,方法返回地址等;每一個方法從調用到執行完畢,對應一個棧幀在虛擬機棧中的入棧和出棧。

二、堆:

線程共享;被全部線程共享的一塊內存區域,在虛擬機啓動時建立,用於存放對象實例。

三、方法區:

線程共享;被全部線程共享的一塊內存區域;用於存儲已被虛擬機加載的類信息,常量,靜態變量等。

四、程序計數器:

線程私有;是當前線程所執行的字節碼的行號指示器,每條線程都要有一個獨立的程序計數器,這類內存也稱爲「線程私有」的內存。

五、本地方法棧:

線程私有;主要爲虛擬機使用到的Native方法服務。

強引用,軟引用和弱引用的區別

強引用:

只有這個引用被釋放以後,對象纔會被釋放掉,只要引用存在,垃圾回收器永遠不會回收,這是最多見的New出來的對象。

軟引用:

內存溢出以前經過代碼回收的引用。軟引用主要用戶實現相似緩存的功能,在內存足夠的狀況下直接經過軟引用取值,無需從繁忙的真實來源查詢數據,提高速度;當內存不足時,自動刪除這部分緩存數據,從真正的來源查詢這些數據。

弱引用:

第二次垃圾回收時回收的引用,短期內經過弱引用取對應的數據,能夠取到,當執行過第二次垃圾回收時,將返回null。弱引用主要用於監控對象是否已經被垃圾回收器標記爲即將回收的垃圾,能夠經過弱引用的isEnQueued方法返回對象是否被垃圾回收器標記。

數組在內存中如何分配

一、簡單的值類型的數組,每一個數組成員是一個引用(指針),引用到棧上的空間(由於值類型變量的內存分配在棧上)

二、引用類型,類類型的數組,每一個數組成員還是一個引用(指針),引用到堆上的空間(由於類的實例的內存分配在堆上)

springmvc的核心是什麼,請求的流程是怎麼處理的,控制反轉怎麼實現的

核心:

控制反轉和麪向切面

請求處理流程:

一、首先用戶發送請求到前端控制器,前端控制器根據請求信息(如URL)來決定選擇哪個頁面控制器進行處理並把請求委託給它,即之前的控制器的控制邏輯部分;

二、頁面控制器接收到請求後,進行功能處理,首先須要收集和綁定請求參數到一個對象,並進行驗證,而後將命令對象委託給業務對象進行處理;處理完畢後返回一個ModelAndView(模型數據和邏輯視圖名);

三、前端控制器收回控制權,而後根據返回的邏輯視圖名,選擇相應的視圖進行渲染,並把模型數據傳入以便視圖渲染;

四、前端控制器再次收回控制權,將響應返回給用戶。

控制反轉如何實現:

咱們每次使用spring框架都要配置xml文件,這個xml配置了bean的id和class。

spring中默認的bean爲單實例模式,經過bean的class引用反射機制能夠建立這個實例。

所以,spring框架經過反射替咱們建立好了實例而且替咱們維護他們。

A須要引用B類,spring框架就會經過xml把B實例的引用傳給了A的成員變量。

mybatis如何處理結果集

MyBatis的結果集是經過反射來實現的。並非經過get/set方法。在實體類中不管是否認義get/set()方法,都是能夠接收到的。

若是面試只是考你這個點的話就恭喜了。若是繼續深問流程,那就須要本身找一些源碼來閱讀了。

java的多態表如今哪裏

主要有兩種表現形式:重載和重寫

重載:

是發生在同一類中,具備相同的方法名,主要是看參數的個數,類型,順序不一樣實現方法的重載的,返回值的類型能夠不一樣。

重寫:

是發生在兩個類中(父類和子類),具備相同的方法名,主要看方法中參數,個數,類型必須相同,返回值的類型必須相同。

    • *

接口有什麼用

一、經過接口能夠實現不相關類的相同行爲,而不須要了解對象所對應的類。

二、經過接口能夠指明多個類須要實現的方法。

三、經過接口能夠了解對象的交互界面,而不需瞭解對象所對應的類。

另:Java是單繼承,接口可使其實現多繼承的功能。

    • *

說說http,https協議

HTTP:

是互聯網上應用最爲普遍的一種網絡協議,是一個客戶端和服務器端請求和應答的標準(TCP),用於從WWW服務器傳輸超文本到本地瀏覽器的傳輸協議,它可使瀏覽器更加高效,使網絡傳輸減小。

HTTPS:

是以安全爲目標的HTTP通道,簡單講是HTTP的安全版,即HTTP下加入SSL層,HTTPS的安全基礎是SSL,所以加密的詳細內容就須要SSL。

區別:

一、https協議須要到ca申請證書,通常免費證書較少,於是須要必定費用。

二、http是超文本傳輸協議,信息是明文傳輸,https則是具備安全性的ssl加密傳輸協議。

三、http和https使用的是徹底不一樣的鏈接方式,用的端口也不同,前者是80,後者是443。

四、http的鏈接很簡單,是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議,比http協議安全。

    • *

說說tcp/ip協議族

TCP/IP協議族是一個四層協議系統,自底而上分別是數據鏈路層、網絡層、傳輸層和應用層。每一層完成不一樣的功能,且經過若干協議來實現,上層協議使用下層協議提供的服務。

一、數據鏈路層負責幀數據的傳遞。

二、網絡層責數據怎樣傳遞過去。

三、傳輸層負責傳輸數據的控制(準確性、安全性)

四、應用層負責數據的展現和獲取。

    • *

tcp五層網絡協議

物理層:

爲數據端設備提供傳送數據的通路,數據通路能夠是一個物理媒體,也能夠是多個物理媒體鏈接而成。

數據鏈路層:

爲網絡層提供數據傳送服務。

網絡層:

路由選擇和中繼、激活,終止網絡鏈接、在一條數據鏈路上覆用多條網絡鏈接,多采起分時複用技術 、差錯檢測與恢復、排序,流量控制、服務選擇、網絡管理 。

傳輸層:

傳輸層是兩臺計算機通過網絡進行數據通訊時,第一個端到端的層次,具備緩衝做用。

應用層:

應用層嚮應用程序提供服務

    • *

TCP與UDP的區別

一、基於鏈接與無鏈接

二、TCP要求系統資源較多,UDP較少; 

三、UDP程序結構較簡單 

四、流模式(TCP)與數據報模式(UDP); 

五、TCP保證數據正確性,UDP可能丟包 

六、TCP保證數據順序,UDP不保證 

    • *

cookie和session的區別,分佈式環境怎麼保存用戶狀態

一、cookie數據存放在客戶的瀏覽器上,session數據放在服務器上。

二、cookie不是很安全,別人能夠分析存放在本地的COOKIE並進行COOKIE欺騙,考慮到安全應當使用session。

三、session會在必定時間內保存在服務器上。當訪問增多,會比較佔用你服務器的性能,考慮到減輕服務器性能方面,應當使用COOKIE。

四、單個cookie保存的數據不能超過4K,不少瀏覽器都限制一個站點最多保存20個cookie。

分佈式環境下的session(舉例兩種):

服務器session複製

原理:任何一個服務器上的session發生改變(增刪改),該節點會把這個 session的全部內容序列化,而後廣播給全部其它節點,無論其餘服務器需不須要session,以此來保證Session同步。

優勢:可容錯,各個服務器間session可以實時響應。

缺點:會對網絡負荷形成必定壓力,若是session量大的話可能會形成網絡堵塞,拖慢服務器性能。

session共享機制

使用分佈式緩存方案好比memcached、redis,可是要求Memcached或Redis必須是集羣。

    • *

GIT和SVN的區別

一、GIT是分佈式的,SVN不是。

二、GIT把內容按元數據方式存儲,而SVN是按文件。

三、GIT分支和SVN的分支不一樣。

四、GIT沒有一個全局的版本號,而SVN有。

五、GIT的內容完整性要優於SVN。

(通常問會不會用,知道這些區別貌似也沒卵用)

請寫一段棧溢出、堆溢出的代碼

遞歸調用能夠致使棧溢出
不斷建立對象能夠致使堆溢出

代碼以下:

<pre style="margin: 0px 0px 0px 22px; white-space: pre-wrap; overflow-wrap: break-word; font-size: 12px !important; font-family: &quot;Courier New&quot; !important;">

public class Test { public void testHeap(){ for(;;){

ArrayList list = new ArrayList (2000);  
     }

} int num=1; public void testStack(){

num++; this.testStack();  
} public static void main(String[] args){  
   Test  t = new Test ();  
   t.testHeap();  
   t.testStack();

}
}</pre>

BIO、NIO和AIO的區別

Java BIO : 同步並阻塞,服務器實現模式爲一個鏈接一個線程,即客戶端有鏈接請求時服務器端就須要啓動一個線程進行處理,若是這個鏈接不作任何事情會形成沒必要要的線程開銷,固然能夠經過線程池機制改善。

Java NIO : 同步非阻塞,服務器實現模式爲一個請求一個線程,即客戶端發送的鏈接請求都會註冊到多路複用器上,多路複用器輪詢到鏈接有I/O請求時才啓動一個線程進行處理。

Java AIO: 異步非阻塞,服務器實現模式爲一個有效請求一個線程,客戶端的I/O請求都是由OS先完成了再通知服務器應用去啓動線程進行處理。

NIO比BIO的改善之處是把一些無效的鏈接擋在了啓動線程以前,減小了這部分資源的浪費(由於咱們都知道每建立一個線程,就要爲這個線程分配必定的內存空間)

AIO比NIO的進一步改善之處是將一些暫時可能無效的請求擋在了啓動線程以前,好比在NIO的處理方式中,當一個請求來的話,開啓線程進行處理,但這個請求所須要的資源尚未就緒,此時必須等待後端的應用資源,這時線程就被阻塞了。

適用場景分析:

 BIO方式適用於鏈接數目比較小且固定的架構,這種方式對服務器資源要求比較高,併發侷限於應用中,JDK1.4之前的惟一選擇,但程序直觀簡單易理解,如以前在Apache中使用。

 NIO方式適用於鏈接數目多且鏈接比較短(輕操做)的架構,好比聊天服務器,併發侷限於應用中,編程比較複雜,JDK1.4開始支持,如在 Nginx,Netty中使用。

 AIO方式使用於鏈接數目多且鏈接比較長(重操做)的架構,好比相冊服務器,充分調用OS參與併發操做,編程比較複雜,JDK7開始支持,在成長中,Netty曾經使用過,後來放棄。

    • *

java中常說的堆和棧,分別是什麼數據結構;另外,爲何要分爲堆和棧來存儲數據

棧是一種具備後進先出性質的數據結構,也就是說後存放的先取,先存放的後取。

堆是一種通過排序的樹形數據結構,每一個結點都有一個值。一般咱們所說的堆的數據結構,是指二叉堆。堆的特色是根結點的值最小(或最大),且根結點的兩個子樹也是一個堆。因爲堆的這個特性,經常使用來實現優先隊列,堆的存取是隨意的。

爲何要劃分堆和棧

一、從軟件設計的角度看,棧表明了處理邏輯,而堆表明了數據。這樣分開,使得處理邏輯更爲清晰。

二、堆與棧的分離,使得堆中的內容能夠被多個棧共享。一方面這種共享提供了一種有效的數據交互方式(如:共享內存),另外一方面,堆中的共享常量和緩存能夠被全部棧訪問,節省了空間。

三、棧由於運行時的須要,好比保存系統運行的上下文,須要進行地址段的劃分。因爲棧只能向上增加,所以就會限制住棧存儲內容的能力。而堆不一樣,堆中的對象是能夠根據須要動態增加的,所以棧和堆的拆分,使得動態增加成爲可能,相應棧中只需記錄堆中的一個地址便可。

四、體現了Java面向對象這一核心特色(也能夠繼續說一些本身的理解)

    • *

爲何要用線程池

那先要明白什麼是線程池

線程池是指在初始化一個多線程應用程序過程當中建立一個線程集合,而後在須要執行新的任務時重用這些線程而不是新建一個線程。

使用線程池的好處

一、線程池改進了一個應用程序的響應時間。因爲線程池中的線程已經準備好且等待被分配任務,應用程序能夠直接拿來使用而不用新建一個線程。

二、線程池節省了CLR 爲每一個短生存週期任務建立一個完整的線程的開銷並能夠在任務完成後回收資源。

三、線程池根據當前在系統中運行的進程來優化線程時間片。

四、線程池容許咱們開啓多個任務而不用爲每一個線程設置屬性。

五、線程池容許咱們爲正在執行的任務的程序參數傳遞一個包含狀態信息的對象引用。

六、線程池能夠用來解決處理一個特定請求最大線程數量限制問題。

    • *

msyql優化經驗

一、對查詢進行優化,應儘可能避免全表掃描,首先應考慮在 where 及 order by 涉及的列上創建索引。

二、應儘可能避免在 where 子句中使用!=或<>操做符,不然引擎將放棄使用索引而進行全表掃描。

三、儘可能使用數字型字段,若只含數值信息的字段儘可能不要設計爲字符型,這會下降查詢和鏈接的性能,並會增長存儲開銷。這是由於引擎在處理查詢和鏈接時會逐個比較字符串中每個字符,而對於數字型而言只須要比較一次就夠了。

四、任何地方都不要使用 select from t ,用具體的字段列表代替「」,不要返回用不到的任何字段。

五、避免頻繁建立和刪除臨時表,以減小系統表資源的消耗。諸如此類,等等等等......

悲觀鎖和樂觀鎖的區別,怎麼實現

悲觀鎖:一段執行邏輯加上悲觀鎖,不一樣線程同時執行時,只能有一個線程執行,其餘的線程在入口處等待,直到鎖被釋放。

樂觀鎖:一段執行邏輯加上樂觀鎖,不一樣線程同時執行時,能夠同時進入執行,在最後更新數據的時候要檢查這些數據是否被其餘線程修改了(版本和執行初是否相同),沒有修改則進行更新,不然放棄本次操做。

悲觀鎖的實現:

//0.開始事務`
begin``;/``begin` `work``;/start ``transaction``; (三者選一就能夠)`
//1.查詢出商品信息`
select` `status ``from` `t_goods ``where` `id=1 ``for` `update``;`
//2.根據商品信息生成訂單`
insert` `into` `t_orders (id,goods_id) ``values` `(``null``,1);`
//3.修改商品status爲2`
update` `t_goods ``set` `status=2;`
//4.提交事務`
commit``;/``commit` `work``;`

樂觀鎖的實現:

1.查詢出商品信息`
select` `(status,status,version) ``from` `t_goods ``where` `id=#{id}`
2.根據商品信息生成訂單`
3.修改商品status爲2`
update` `t_goods`
set` `status=2,version=version+1`
where` `id=#{id} ``and` `version=#{version};`
相關文章
相關標籤/搜索