1.HashMap 和 Hashtable 有什麼區別?HashMap 和 HashSet 呢?
HashMap 和 Hashtable 區別:
- hashmap線程不安全、hashtable線程安全
- hashmap繼承自abstractmap、hashtable繼承dictionary
- hashmap允許存儲null鍵值(存一個null鍵和多個value是null)、hashtable不允許
- hashtable直接使用hashcode,hashmap用擾動函數處理hashcode(hashcode右移16位在與原hashcode異或操作,爲了減少hashcode衝突)
- hashmap初始容量16,hashtable11
- hashmap擴容old*2;hashtable擴容old*2+1
hashset:
- 底層實現是hashmap,因爲hashset內部元素不能相同,所以存儲方式爲hashmap的key值。
- 需要重寫hashcode函數和equals函數,通過hashcode直接定位到地址,在通過equals比較對象。
- 元素無序
2.final 關鍵字用於什麼場景?
- 字段不可修改,引用不可修改地址
- 方法不能重寫
- 類不能繼承
包含final域的對象的引用和讀這個final域,不能重排序;構造函數對final域的寫入和這個對象的引用被賦值,不能重排序。
使用場景:
- 不可改變域
- 多線程使用場景,使用final關鍵字或者:synchronized、volatile、鎖
3.ConcurrentHashMap 如何實現線程同步?
hashmap的線程安全版,引入segment,每一個segment都是線程安全的,相當於一個hashtable,因此,ConcurrentHashMap也不允許出現null。這樣就把整個類鎖變成了局部鎖,用哪一個segment就給哪一個segment加鎖。減少競爭,提高效率。
對於jdk1.8的改進:
- 取消的segment,轉而採用數組元素作爲鎖。把鎖的粒度從多個node變成一個node,進一步減少鎖競爭
- 鏈表大於8的時候轉化爲紅黑樹
實現線程同步:
元素Node,字段修飾爲final和volatile,採用樂觀鎖CAS,和分而治之的思想
-
put操作和初始化操作:
- volatile字段,標識位,表示當前是否有線程在初始化,volatile字段保證了所有線程的可見。
- CAS機制,保證只有一個線程能夠初始化
-
size()/判斷大小
首先通過CAS機制,如果沒有線程競爭,直接遞增count,失敗就初始化桶,每一個桶併發的記錄(同樣是CAS機制,最大程度利用併發),如果桶計數頻繁失敗就擴容桶。
4.Map 遍歷的兩種方式?
keyset和entryset,前者是獲得key的集合,後者是獲得key-value的集合,返回的都是set視圖,因爲set有迭代器iterator可以用,通過iterator.next來遍歷。
【Java 面試那點事】
這裏致力於分享 Java 面試路上的各種知識,無論是技術還是經驗,你需要的這裏都有!
這裏可以讓你【快速瞭解 Java 相關知識】,並且【短時間在面試方面有跨越式提升】
面試路上,你不孤單!