18年11月份面試題積累【集合】

HashMap 和 Hashtable 的區別
1.hashMap去掉了HashTable 的contains方法,但是加上了containsValue()和containsKey()方法。
2.hashTable同步的,而HashMap是非同步的,效率上逼hashTable要高。
3.hashMap允許空鍵值,而hashTable不允許。
4.初始size爲16,擴容:newsize = oldsize2,size一定爲2的n次冪
初始size爲11,擴容:newsize = olesize
2+1

HashMap 和 ConcurrentHashMap 的區別
ConcurrentHashMap是線程安全的HashMap的實現。

底層採用分段的數組+鏈表實現,線程安全
通過把整個Map分爲N個Segment,可以提供相同的線程安全,但是效率提升N倍,默認提升16倍。(讀操作不加鎖,由於HashEntry的value變量是 volatile的,也能保證讀取到最新的值。)
Hashtable的synchronized是針對整張Hash表的,即每次鎖住整張表讓線程獨佔,ConcurrentHashMap允許多個修改操作併發進行,其關鍵在於使用了鎖分離技術

map遍歷方法
1、Iterator遍歷

   Iterator<Map.Entry<String,String>> it = map.entrySet().iterator();
      while(it.hasNext()){
        Map.Entry<String,String> entry=it.next();
        System.out.println("key=" +entry.getKey() +" and value="+entry.getValue());
    }

2、取值遍歷

    for(String key:map.keySet()){
        System.out.println("key="+key+"and value=" +map.get(key));
    }

3、遍歷所有的Value值
該方式取得不了key值,直接遍歷map中存放的value值

  for(String v:map.values()){
        System.out.println("value= "+ v);
  }

4、使用entrySet遍歷

  for(Map.Entry<String,String > entry:map.entrySet()){
        System.out.println("key=" +entry.getKey() +" and value="+entry.getValue());
 }

List遍歷:for,foreach Iterator 速度比較
如果是ArrayList,用三種方式遍歷的速度是for>Iterator>foreach,速度級別基本一致;
如果是LinkedList,則三種方式遍歷的差距很大了,數據量大時越明顯(一般是超過100000級別),用for遍歷的效率遠遠落後於foreach和Iterator,Iterator>foreach>>>for;

1:測試發現foreach和Iterator基本上都在一個速度級別,但Iterator會稍稍快於foreach,事實上,foreach就是基於Iterator實現的,可通過反編譯工具看到。
所以foreach和Iterator基本是效率相當的,慢的時間猜測就是foreach隱式轉換成Iterator所消耗的時間.

2:接下來要解釋的是爲什麼ArrayList的遍歷中for比Iterator快,而LinkedList中卻是Iterator遠快於for?這得從ArrayList和LinkedList兩者的數據結構說起了:
ArrayList是基於索引(index)的數組,索引在數組中搜索和讀取數據的時間複雜度是O(1),但是要增加和刪除數據卻是開銷很大的,因爲這需要重排數組中的所有數據。
LinkedList的底層實現則是一個雙向循環帶頭節點的鏈表,因此LinkedList中插入或刪除的時間複雜度僅爲O(1),但是獲取數據的時間複雜度卻是O(n)。

明白了兩種List的區別之後,就知道,ArrayList用for循環隨機讀取的速度是很快的,因爲ArrayList的下標是明確的,讀取一個數據的時間複雜度僅爲O(1)。但LinkedList若是用for來遍歷效率很低,讀取一個數據的時間複雜度就達到了爲O(n)。而用Iterator的next()則是順着鏈表節點順序讀取數據的效率就很高了。

最後總結:
1:ArrayList用三種遍歷方式都差得不算太多,一般都會用for或者foreach,因爲Iterator寫法相對複雜一些。
2:LinkedList的話,推薦使用foreach或者Iterator(數據量越大時,三者方法差別明顯)。

PS:
Iterator實例化方法
Iterator iterator = list.iterator()
while(iterator.hasNext()){
T t = iterator.next();
System.out.println(t);
}




tomcat配置,項目請求路徑的配置,端口號的配置
conf目錄下 server.xml
tomcat熱部署和熱加載
文件服務器的搭建

public private protect的權限區別
在這裏插入圖片描述

hibernate和mybatis的緩存機制
hibernate
一級緩存(session級別)
二級緩存(sessionFactory級別)
hibernate
分爲一級緩存即session緩存也叫事務級別的緩存
二級緩存sessionFactory即應用級別的緩存
三級緩存即查詢緩存。

mybatis
一級緩存是SqlSession級別的緩存,緩存的數據只在SqlSession內有效
二級緩存是mapper級別的緩存,同一個namespace公用這一個緩存,所以對SqlSession是共享的

spring的依賴注入有幾種
註解注入方式、set注入方式、構造器注入方式、靜態工廠注入方式

myBatis的$和#
#可以防止Sql 注入,它會將所有傳入的參數作爲一個字符串來處理。
$ 則將傳入的參數拼接到Sql上去執行,一般用於表名和字段名參數,$ 所對應的參數應該由服務器端提供,前端可以用參數進行選擇,避免 Sql 注入的風險

@Autowired與@Resource的區別

@pathvariable @RequestBody的區別
@requestparam

spring配置的bean類怎麼調用

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
 User user = (User) context.getBean("user");

JSP和Servlet有哪些相同點和不同點,他們之間的聯繫是什麼?

zookeeper的選取leader 原理
kafka的運行的機制

java線程池的瞭解
ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,
BlockingQueue workQueue);

synchronized和lock鎖的區別,重入鎖 (需要手動釋放)
兩者區別:
1.首先synchronized是java內置關鍵字,在jvm層面,Lock是個java類;
2.synchronized無法判斷是否獲取鎖的狀態,Lock可以判斷是否獲取到鎖;
3.synchronized會自動釋放鎖(a 線程執行完同步代碼會釋放鎖 ;b 線程執行過程中發生異常會釋放鎖),Lock需在finally中手工釋放鎖(unlock()方法釋放鎖),否則容易造成線程死鎖;
4.用synchronized關鍵字的兩個線程1和線程2,如果當前線程1獲得鎖,線程2線程等待。如果線程1阻塞,線程2則會一直等待下去,而Lock鎖就不一定會等待下去,如果嘗試獲取不到鎖,線程可以不用一直等待就結束了;
5.synchronized的鎖可重入、不可中斷、非公平,而Lock鎖可重入、可中斷、可公平(兩者皆可)
6.Lock鎖適合大量同步的代碼的同步問題,synchronized鎖適合代碼少量的同步問題。

樂觀鎖和悲觀鎖
volatile可以保證線程安全嗎?手寫了個例子驗證一下

線程池發生死鎖的情況
死鎖的根本原因1)是多個線程涉及到多個鎖,這些鎖存在着交叉,所以可能會導致了一個鎖依賴的閉環;2)默認的鎖申請操作是阻塞的。所以要避免死鎖,就要在一遇到多個對象鎖交叉的情況,就要仔細審查這幾個對象的類中的所有方法,是否存在着導致鎖依賴的環路的可能性。要採取各種方法來杜絕這種可能性。

request 用戶端請求,此請求會包含來自GET/POST請求的參數
response 網頁傳回用戶端的迴應
session 與請求有關的會話期
application servlet 正在執行的內容
out 用來傳送回應的輸出
exception 針對錯誤網頁,未捕捉的例外
page JSP網頁本身
pageContext 網頁的屬性是在這裏管理
exception 針對錯誤網頁,未捕捉的例外
config servlet的構架部件

jdbc的流程
1、 加載JDBC驅動程序:
2、 提供JDBC連接的URL
3、創建數據庫的連接
4、創建一個Statement
5、執行sql
要連接數據庫,需要向java.sql.DriverManager請求並獲得Connection對象, 該對象就代表一個數據庫的連接。
使用DriverManager的getConnectin(String url , String username , String password )方法傳入指定的欲連接的數據庫的路徑、數據庫的用戶名和 密碼來獲得。

MySql和Orcale的分頁
mysql --> limit(n,m) 兩個參數的意義
oracle–> rownum
Hibernate --> setfirstResult(),setMaxResult()

sql查詢(批量插入,批量更新)
insert into student values
(1,小明),(2,小黃),(3,小天)

更新多條記錄的同一個字段爲同一個值
UPDATE course SET name=‘course1’ WHERE id in(‘id1’,‘id2’,'id3);

更新多條記錄爲多個字段爲不同的值
MySQL沒有提供直接的方法來實現批量更新,但可以使用case when語法來實現這個功能。
UPDATE course
SET name = CASE id
WHEN 1 THEN ‘name1’
WHEN 2 THEN ‘name2’
WHEN 3 THEN ‘name3’
END,
title = CASE id
WHEN 1 THEN ‘New Title 1’
WHEN 2 THEN ‘New Title 2’
WHEN 3 THEN ‘New Title 3’
END
WHERE id IN (1,2,3)

case when then end可用於sql行列互換查詢
題目:數據庫中有一張如下所示的表,表名爲sales。
年 季度 銷售量
1991 1 11
1991 2 12
1991 3 13
1991 4 14
1992 1 21
1992 2 22
1992 3 23
1992 4 24

要求:寫一個SQL語句查詢出如下所示的結果。
年 一季度 二季度 三季度 四季度
1991 11 12 13 14
1992 21 22 23 24

我給出的答案是這樣的:
select 年,
sum(case when 季度=1 then 銷售量 else 0 end) as 一季度,
sum(case when 季度=2 then 銷售量 else 0 end) as 二季度,
sum(case when 季度=3 then 銷售量 else 0 end) as 三季度,
sum(case when 季度=4 then 銷售量 else 0 end) as 四季度
from sales group by 年;

集羣和分佈式的關係
簡單的解釋:
小飯店原來只有一個廚師,切菜洗菜備料炒菜全乾。後來客人多了,廚房一個廚師忙不過來,又請了個廚師,兩個廚師都能炒一樣的菜,這兩個廚師的關係是集羣。爲了讓廚師專心炒菜,把菜做到極致,又請了個配菜師負責切菜,備菜,備料,廚師和配菜師的關係是分佈式,一個配菜師也忙不過來了,又請了個配菜師,兩個配菜師關係是集羣

負載均衡的幾種常用方式
1、輪詢(默認)
每個請求按時間順序逐一分配到不同的後端服務器,如果後端服務器down掉,能自動剔除。
upstreambackserver {
server192.168.0.14;
server192.168.0.15;
}
2、weight
指定輪詢機率,weight和訪問比率成正比,用於後端服務器性能不均的
情況。
upstreambackserver {
server192.168.0.14weight= 3;
server192.168.0.15weight= 7;
}
權重越高,在被訪問的概率越大,如上例,分別是30%,70%。
3、上述方式存在一個問題就是說,在負載均衡系統中,假如用戶在某臺服務器上登錄了,那麼該用戶第二次請求的時候,因爲我們是負載均衡系統,每次請求都會重新定位到服務器集羣中的某一個,那麼已經登錄某一個服務器的用戶再重新定位到另一個服務器,其登錄信息將會丟失,這樣顯然是不妥的。
我們可以採用ip_hash指令解決這個問題,如果客戶已經訪問了某個服務器,當用戶再次訪問時,會將該請求通過哈希算法,自動定位到該服務器。
每個請求按訪問ip的hash結果分配,這樣每個訪客固定訪問一個後端服務器,可以解決session的問題。
upstream backserver {
ip_hash;
server192.168.0.14: 88;
server192.168.0.15: 80;
}
4、fair(第三方)
按後端服務器的響應時間來分配請求,響應時間短的優先分配。
upstream backserver {
serverserver1;
serverserver2;
fair;
}
5、url_hash(第三方)
按訪問url的hash結果來分配請求,使每個url定向到同一個後端服務器,後端服務器爲緩存時比較有效。
upstreambackserver {
serversquid1: 3128;
serversquid2: 3128;
hash$request_uri;
hash_methodcrc32;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章