【魯班學院】面試總結:Java高級篇(上):集合的類型以及從新認識HashMap

1.你用過哪些集合類?

大公司最喜歡問的Java集合類面試題
40個Java集合面試問題和答案
java.util.Collections 是一個包裝類。它包含有各類有關集合操做的靜態多態方法。
java.util.Collection 是一個集合接口。它提供了對集合對象進行基本操做的通用接口方法。

Collection
複製代碼
├List
    
    │├LinkedList
    
    │├ArrayList
    
    │└Vector
    
    │ └Stack
    
    └Set
    
    Map
    
    ├Hashtable
    
    ├HashMap
    
    └WeakHashMap
複製代碼

ArrayList、HashMap、TreeMap和HashTable類提供對元素的隨機訪問。java

(1)線程安全面試

Vector
HashTable(不容許插空值)
複製代碼

(2)非線程安全算法

ArrayList
LinkedList
HashMap(容許插入空值)
HashSet
TreeSet
TreeMap(基於紅黑樹的Map實現)
複製代碼

2.你說說 arraylist 和 linkedlist 的區別?

ArrayList和LinkedList二者都實現了List接口,可是它們之間有些不一樣。數據庫

一、ArrayList是由Array所支持的基於一個索引的數據結構,因此它提供對元素的隨機訪問。 二、與ArrayList相比,在LinkedList中插入、添加和刪除一個元素會更快。 三、LinkedList比ArrayList消耗更多的內存,由於LinkedList中的每一個節點存儲了先後節點的引用。編程

3.HashMap 底層是怎麼實現的?還有什麼處理哈希衝突的方法?

處理哈希衝突的方法: 解決HashMap通常沒有什麼特別好的方式,要不擴容從新hash要不優化衝突的鏈表結構。數組

1.開放定地址法-線性探測法 2.開放定地址法-平方探查法 3.鏈表解決-能夠用紅黑樹提升查找效率 緩存

在這裏插入圖片描述
HashMap簡介: HashMap 是一個散列表,它存儲的內容是鍵值對(key-value)映射。 HashMap 繼承於AbstractMap,實現了Map、Cloneable、java.io.Serializable接口。 HashMap 的實現不是同步的,這意味着它不是線程安全的,但能夠用 Collections的synchronizedMap方法使HashMap具備線程安全的能力。它的key、value均可覺得null。此外,HashMap中的映射不是有序的。

HashMap 的實例有兩個參數影響其性能:「初始容量」 和 「加載因子」。安全

初始容量默認是16。默認加載因子是 0.75,這是在時間和空間成本上尋求一種折衷。加載因子太高雖然減小了空間開銷,但同時也增長了查詢成本。HashMap是數組+鏈表+紅黑樹(JDK1.8增長了紅黑樹部分)實現的,當鏈表長度太長(默認超過8)時,鏈表就轉換爲紅黑樹。bash

4.Java8系列之從新認識HashMap

功能實現-方法: 一、肯定哈希桶數組索引位置 :這裏的Hash算法本質上就是三步:取key的hashCode值、高位運算、取模運算。服務器

方法一:static final int hash(Object key) { //jdk1.8 & jdk1.7int h;// h = key.hashCode() 爲第一步 取hashCode值// h ^ (h >>> 16) 爲第二步 高位參與運算return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}

`方法二:static int indexFor(int h, int length) { //jdk1.7的源碼,jdk1.8沒有這個方法,可是實現原理同樣的return h & (length-1); //第三步 取模運算}`
複製代碼

1.分析HashMap的put方法 2.擴容機制:原來的兩倍

在這裏插入圖片描述

5.熟悉什麼算法,還有說說他們的時間複雜度?

經典排序算法總結與實現

在這裏插入圖片描述

6.ArrayList和Vector的底層代碼和他們的增加策略,它們是如何進行擴容的?

ArrayList 默認數組大小是10,其中ensureCapacity擴容,trimToSize容量調整到適中,擴展後數組大小爲((原數組長度1.5)與傳遞參數中較大者。

Vector的擴容,是能夠指定擴容因子,同時Vector擴容策略是:1.原來容量的2倍,2.原來容量+擴容參數值。(*詳細內容能夠配合閱讀源碼)

7.jvm 原理,程序運行區域劃分

問:Java運行時數據區域? 回答:包括程序計數器、JVM棧、本地方法棧、方法區、堆。 問:方法區裏存放什麼? 本地方法棧:和jvm棧所發揮的做用相似,區別是jvm棧爲jvm執行java方法(字節碼)服務,而本地方法棧爲jvm使用的native方法服務。 JVM棧:局部變量表、操做數棧、動態連接、方法出口。 方法區:用於存儲已被虛擬機加載的類信息,常量、靜態變量、即時編譯器編譯後的代碼等。 堆:存放對象實例。

8.minor GC 與 Full GC,分別何時會觸發? 分別採用哪一種垃圾回收算法?簡單介紹算法。

GC(或Minor GC):收集 生命週期短的區域(Young area)。 Full GC (或Major GC):收集生命週期短的區域(Young area)和生命週期比較長的區域(Old area)對整個堆進行垃圾收集。

新生代一般存活時間較短基於Copying算法進行回收,將可用內存分爲大小相等的兩塊,每次只使用其中一塊;當這一塊用完了,就將還活着的對象複製到另外一塊上,而後把已使用過的內存清理掉。在HotSpot裏,考慮到大部分對象存活時間很短將內存分爲Eden和兩塊Survivor,默認比例爲8:1:1。代價是存在部份內存空間浪費,適合在新生代使用。

老年代與新生代不一樣,老年代對象存活的時間比較長、比較穩定,所以採用標記(Mark)算法來進行回收,所謂標記就是掃描出存活的對象,而後再進行回收未被標記的對象,回收後對用空出的空間要麼進行合併、要麼標記出來便於下次進行分配,總之目的就是要減小內存碎片帶來的效率損耗。 在執行機制上JVM提供了串行GC(Serial MSC)、並行GC(Parallel MSC)和併發GC(CMS)。

Minor GC ,Full GC 觸發條件 Minor GC觸發條件:當Eden區滿時,觸發Minor GC。

Full GC觸發條件: 一、調用System.gc時,系統建議執行Full GC,可是沒必要然執行。 二、老年代空間不足。 三、方法去空間不足。 四、經過Minor GC後進入老年代的平均大小大於老年代的可用內存。 五、由Eden區、From Space區向To Space區複製時,對象大小大於To Space可用內存,則把該對象轉存到老年代,且老年代的可用內存小於該對象大小。

9.HashMap 實現原理

在java編程語言中,最基本的結構就是兩種,一個是數組,另一個是模擬指針(引用),全部的數據結構均可以用這兩個基本結構來構造的,HashMap也不例外。HashMap其實是一個「鏈表散列」的數據結構,即數組和鏈表的結合體。

10.java.util.concurrent 包下使用過哪些

(1).阻塞隊列
BlockingQueue( ArrayBlockingQueue, DelayQueue, LinkedBlockingQueue,SynchronousQueue,LinkedTransferQueue,LinkedBlockingDeque)
(2).ConcurrentHashMap
(3).Semaphore–信號量
(4) .CountDownLatch–閉鎖
(5).CyclicBarrier–柵欄
(6).Exchanger–交換機
(7).Executor-
>ThreadPoolExecutor,ScheduledThreadPoolExecutor

Semaphore semaphore = new Semaphore(1);//critical section semaphore.acquire();...semaphore.release(); 
複製代碼

9.鎖

Lock–ReentrantLock,ReadWriteLock,Condition,LockSupport

Lock lock = new ReentrantLock();lock.lock();//critical section lock.unlock();
複製代碼

10.concurrentMap 和 HashMap 區別

1.hashMap能夠有null的鍵,concurrentMap不能夠有 2.hashMap是線程不安全的,在多線程的時候須要Collections.synchronizedMap(hashMap),ConcurrentMap使用了重入鎖保證線程安全。 3.在刪除元素時候,二者的算法不同。 ConcurrentHashMap和Hashtable主要區別就是圍繞着鎖的粒度以及如何鎖,能夠簡單理解成把一個大的HashTable分解成多個,造成了鎖分離。

11.信號量是什麼,怎麼使用?volatile關鍵字是什麼?

`信號量-semaphore:荷蘭著名的計算機科學家Dijkstra 於1965年提出的一個同步機制。是在多線程環境下使用的一種設施, 它負責協調各個線程,以保證它們可以正確、合理的使用公共資源。

整形信號量:表示共享資源狀態,且只能由特殊的原子操做改變整型量。 同步與互斥:同類進程爲互斥關係(打印機問題),不一樣進程爲同步關係(消費者生產者)。

使用volatile關鍵字是解決同步問題的一種有效手段。 java volatile關鍵字預示着這個變量始終是「存儲進入了主存」。更精確的表述就是每一次讀一個volatile變量,都會從主存讀取,而不是CPU的緩存。一樣的道理,每次寫一個volatile變量,都是寫回主存,而不只僅是CPU的緩存。 Java 保證volatile關鍵字保證變量的改變對各個線程是可見的。`

在這裏插入圖片描述

13.阻塞隊列了解嗎?怎麼使用?!

阻塞隊列 (BlockingQueue)是Java util.concurrent包下重要的數據結構,BlockingQueue提供了線程安全的隊列訪問方式:當阻塞隊列進行插入數據時,若是隊列已滿,線程將會阻塞等待直到隊列非滿;從阻塞隊列取數據時,若是隊列已空,線程將會阻塞等待直到隊列非空。併發包下不少高級同步類的實現都是基於BlockingQueue實現的。

在這裏插入圖片描述

在這裏插入圖片描述

以ArrayBlockingQueue爲例,咱們先來看看代碼:

public void put(E e) throws InterruptedException {if (e == null) throw new
NullPointerException();final ReentrantLock lock = this.lock;lock.lockInterruptibly();try
{while (count == items.length)notFull.await();enqueue(e);} finally {lock.unlock();}}
複製代碼

從put方法的實現能夠看出,它先獲取了鎖,而且獲取的是可中斷鎖,而後判斷當前元素個數是否等於數組的長度,若是相等,則調用notFull.await()進行等待,當被其餘線程喚醒時,經過enqueue(e)方法插入元素,最後解鎖。

/*** Inserts element at current put position, advances, and signals.* Call only when
holding lock.*/private void enqueue(E x) {// assert lock.getHoldCount() == 1;// assert items[putIndex] == null;final Object[]
 items = this.items;items[putIndex] = x;if 
 (++putIndex == items.length) putIndex = 0;count++;notEmpty.signal();}
複製代碼

插入成功後,經過notEmpty喚醒正在等待取元素的線程。

13.Java中的NIO,BIO,AIO分別是什麼?

IO的方式一般分爲幾種,同步阻塞的BIO、同步非阻塞的NIO、異步非阻塞的AIO

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

在JDK1.4以前,用Java編寫網絡請求,都是創建一個ServerSocket,而後,客戶端創建Socket時 就會詢問是否有線程能夠處理,若是沒有,要麼等待,要麼被拒絕。即:一個鏈接,要求Server 對應一個處理線程。

2.NIO,同步非阻塞IO,簡單理解:一個請求一個線程.NIO方式適用於鏈接數目多且鏈接比較短(輕操做)的架構,好比聊天服務器,併發侷限於應用中,編程比較複雜,JDK1.4開始支持。

NIO自己是基於事件驅動思想來完成的,其主要想解決的是BIO的大併發問題: 在使用同步I/O的網絡應用中,若是要同時處理多個客戶端請求,或是在客戶端要同時和多個服務器進行通信,就必須使用多線程來處理。也就是說,將每個客戶端請求分配給一個線程來單獨處理。這樣作雖然能夠達到咱們的要求,但同時又會帶來另一個問題。 因爲每建立一個線程,就要爲這個線程分配必定的內存空間(也叫工做存儲器),並且操做系統自己也對線程的總數有必定的限制。若是客戶端的請求過多,服務端程序可能會由於不堪重負而拒絕客戶端的請求,甚至服務器可能會所以而癱瘓。

3.AIO,異步非阻塞IO,簡單理解:一個有效請求一個線程.AIO方式使用於鏈接數目多且鏈接比較長(重操做)的架構,好比相冊服務器,充分調用OS參與併發操做,編程比較複雜,JDK7開始支持。

14.類加載機制是怎樣的?

JVM中類的裝載是由ClassLoader和它的子類來實現的,Java ClassLoader是一個重要的Java運行時系統組件。它負責在運行時查找和裝入類文件的類。 類加載的五個過程:加載、驗證、準備、解析、初始化。

從類被加載到虛擬機內存中開始,到卸御出內存爲止,它的整個生命週期分爲7個階段,加載(Loading)、驗證(Verification)、準備(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸御(Unloading)。其中驗證、準備、解析三個部分統稱爲鏈接。

在這裏插入圖片描述

15.什麼是冪等性?

所謂冪等,簡單地說,就是對接口的屢次調用所產生的結果和調用一次是一致的。 那麼咱們爲何須要接口具備冪等性呢?設想一下如下情形:

•在App中下訂單的時候,點擊確認以後,沒反應,就又點擊了幾回。在這種狀況下,若是沒法保證該接口的冪等性,那麼將會出現重複下單問題。 •在接收消息的時候,消息推送重複。若是處理消息的接口沒法保證冪等,那麼重複消費消息產生的影響可能會很是大。

16.有哪些 JVM 調優經驗?

Jvm參數總結:http://linfengying.com/?p=2470

◾內存參數

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述
!

在這裏插入圖片描述

上面有7中收集器,分爲兩塊,上面爲新生代收集器,下面是老年代收集器。若是兩個收集器之間存在連線,就說明它們能夠搭配使用。

在這裏插入圖片描述

17.分佈式 CAP 瞭解嗎?

一致性(Consistency) 可用性(Availability) 分區容忍性(Partition tolerance)

18.ava中HashMap的key值要是爲類對象則該類須要知足什麼條件?

須要同時重寫該類的hashCode()方法和它的equals()方法。

` 當程序試圖將一個 key-value 對放入 HashMap 中時,程序首先根據該 key 的 hashCode() 返回值決定該 Entry 的存儲位置:

若是兩個 Entry 的 key 的 hashCode() 返回值相同,那它們的存儲位置相同。 若是這兩個 Entry 的 key 經過 equals 比較返回 true,新添加 Entry 的 value 將覆蓋集合中原有 Entry 的 value,但 key 不會覆蓋。 若是這兩個 Entry 的 key 經過 equals 比較返回 false,新添加的 Entry 將與集合中原有 Entry 造成 Entry 鏈,並且新添加的 Entry 位於 Entry 鏈的頭部——具體說明繼續看 addEntry() 方法的說明。`

19Java 垃圾回收會出現不可回收的對象嗎?怎麼解決內存泄露問題?怎麼定位問題源?

通常不會有不可回收的對象,由於如今的GC會回收不可達內存。

20.終止線程有幾種方式?終止線程標記變量爲何是 valotile 類型?

1.線程正常執行完畢,正常結束 2.監視某些條件,結束線程的不間斷運行 3.使用interrupt方法終止線程

在定義exit時,使用了一個Java關鍵字volatile,這個關鍵字的目的是使exit同步,也就是說在同一時刻只能由一個線程來修改exit的值。

21.用過哪些併發的數據結構? cyclicBarrier 什麼功能?信號量做用?數據庫讀寫阻塞怎麼解決?

•主要有鎖機制,而後基於CAS的concurrent包。 •CyclicBarrier的字面意思是可循環使用(Cyclic)的屏障(Barrier)。它要作的事情是,讓一組線程到達一個屏障(也能夠叫同步點)時被阻塞,直到最後一個線程到達屏障時,屏障纔會開門,全部被屏障攔截的線程纔會繼續幹活。 CyclicBarrier默認的構造方法是CyclicBarrier(int parties),其參數表示屏障攔截的線程數量,每一個線程調用await方法告訴CyclicBarrier我已經到達了屏障,而後當前線程被阻塞。 •CountDownLatch的計數器只能使用一次。而CyclicBarrier的計數器可使用reset() 方法重置。 •Semaphore(信號量)是用來控制同時訪問特定資源的線程數量,它經過協調各個線程,以保證合理的使用公共資源。 不少年以來,我都以爲從字面上很難理解Semaphore所表達的含義,只能把它比做是控制流量的紅綠燈,好比XX馬路要限制流量,只容許同時有一百輛車在這條路上行使,其餘的都必須在路口等待,因此前一百輛車會看到綠燈,能夠開進這條馬路,後面的車會看到紅燈,不能駛入XX馬路,可是若是前一百輛中有五輛車已經離開了XX馬路,那麼後面就容許有5輛車駛入馬路。 這個例子裏說的車就是線程,駛入馬路就表示線程在執行,離開馬路就表示線程執行完成,看見紅燈就表示線程被阻塞,不能執行。

相關文章
相關標籤/搜索