天天看點

【面經分析】mysql建立索引的幾大原則、List,Set,Map、ConcurrentHashMap的實作原理

1、項目的超賣問題如何解決?

首先超賣問題的出現有兩個原因,

第一個是一個使用者同一時刻發出多次請求,當時庫存是夠的,然後就出現了一個使用者秒殺多件商品;

第二個是資料庫底層邏輯沒有對庫存數量是否>0進行判斷,進而導緻庫存數量減到了負數。

是以解決方法有兩個,在背景的秒殺表中,對使用者id和商品id設定一個唯一索引,防止一個使用者同時秒殺多件商品;

第二就是在sql語句的邏輯中,對庫存數量count進行判斷是否>0才減庫存。

2、排序算法有哪些?

快排、歸并、堆、冒泡、選擇、希爾、桶、計數排序、基數排序

3、堆排序的過程?

将無序序列建構成一個堆,根據升序降序需求選擇大頂堆或小頂堆;(升序大頂堆,降序小頂堆)

将堆頂元素和末尾元素交換,将最大元素沉到數組末端;

重新調整結構,使其滿足堆定義,然後繼續交換堆頂元素與目前末尾元素,反複執行調整+交換步驟,直到整個序列有序。

為啥時間複雜度是O(logn),因為交換并重建堆的過程中,需要交換n-1次,重建堆的過程中,是根據完全二叉樹的性質逐漸遞減的,近似為nlogn。

4、Object類有哪些方法?

【面經分析】mysql建立索引的幾大原則、List,Set,Map、ConcurrentHashMap的實作原理

5、HashMap的容量為什麼要初始化為2的n次幂

計算index的方法:index = (hash & 0x7FFFFFFF) % tab.length

先說說哈希表的映射過程,看底層源碼可以發現,是hashcode & (length - 1)來達到一個取餘的效果,之是以用位運算是因為效率高一些.假如說哈希表的長度是2的n次幂的話,length -1就相當于一個掩碼,能夠獲得hashcode的低位,hashcode的低位實際就是餘數.

6、HashMap和ConcurrentHashMap的差別?

參考連結:https://www.cnblogs.com/chengxiao/p/6842045.html

  • 線程安全。HashMap線程不安全,ConcurrentHashMap線程安全;
  • 底層實作。HashMap底層是通過數組+連結清單+紅黑樹實作的,concurrentHashMap是通過segment數組采用分段鎖政策,實作的。
Segment是一個子哈希表,Segment裡維護了一個HashEntry數組,并發環境下對于并發環境下,對于不同Segment的資料進行操作是不用考慮鎖競争的。(就按預設的ConcurrentLeve為16來講,理論上就允許16個線程并發執行

7、ConcurrentHashMap的實作原理

ConcurrentHashMap内部使用段來表示這些不同的部分,每個段都是一個小的HashTable,他們有自己的鎖,隻要多個修改操作發生在不同的段上,就可以并發執行。JDK1.8的實作降低鎖的粒度,JDK1.7版本鎖的粒度是基于Segment的,包含多個HashEntry,而JDK1.8鎖的粒度就是HashEntry(首節點)。

【面經分析】mysql建立索引的幾大原則、List,Set,Map、ConcurrentHashMap的實作原理

兩次哈希的過程,第一次确定segment,第二次定位到元素所在連結清單的頭部。

缺點:

ConcurrentHashMap 是設計為非阻塞的。在更新時會局部鎖住某部分資料,但不會把整個表都鎖住。同步讀取操作則是完全非阻塞的,好處是在保證合理的同步前提下,效率很高,壞處是讀取操作不能保證反映最近的更新。

擴容:

在JDK7的時候,采用的是分段鎖的機制,ConcurrentHashMap維護了一個Segment數組,Segment這個類繼承了重入鎖ReentrantLock,并且該類維護了一個HashEntry<K,V>[] table數組。

擴容的實作:先對數組的長度增加一倍,然後周遊原來的舊table數組,将每一個數組元素遷移到新的數組裡,遷移完畢後,将新數組的引用直接替換舊的。在遷移連結清單時,用了兩個for循環,第一個for的目的是為了判斷是否有遷移位置一樣的元素

8、List,Set,Map 三者的差別,使用場景,常見的實作類

差別:

  • list:變長數組,有序,檢索效率高,能夠根據下标直接擷取資料,插入删除效率低。适用于查找操作比較多的情況
  • set:自動去重,檢索效率低(因為存儲位置是由hashcode決定的,是以存儲的對象必須有equals方法,并且沒有下标,周遊隻能用疊代)
  • map:存儲的是k-v鍵值對,map中不能包含重複的key

常見的實作類:

  • list:ArrayList、LinkedList、Vector
  • Set:HashSet、TreeSet、LinkedHashSet
  • map:HashMap、HashTable、treemap

HashSet:查詢速度最快的集合,内部是以hashCode實作的。不保證set的疊代順序

TreeSet:是二叉樹實作的,基于TreeMap,生成一個總是處于排序狀态的set,内部以TreeMap來實作,不允許放入null值。

TreeMap:有序散清單,實作SortedMap接口,底層通過紅黑樹實作。

9、Java注解

  • @Autowired:自動按類型注入,如果有多個比對按照bean id查找,查找不到會報錯;
  • @Qualifier:自動按照類型注入的基礎上,按照bean id查找,變量注入時,必須搭配@Autowired,給方法注入時,可用單獨使用;
  • @Resource:直接按照bean id注入,隻能注入bean類型。
  • @Value:用于注入基本資料類型和String類型。

10、mysql建立索引的幾大原則

  • 選擇唯一性索引
  • 為經常需要排序、分組和聯合操作的字段建立索引(ORDER BY、GROUP BY、DISTINCT和UNION)
  • 為經常需要作為查詢條件的字段建立索引
  • 限制索引的數目
  • 盡量使用資料量少的索引
  • 盡量使用字首來索引
  • 删除不再使用或者很少使用的索引
  • 最左字首比對原則
  • 盡量選區分度高的列作為索引
  • 索引列不能參與計算,保持列幹淨
  • 當單個索引字段查詢資料很多,區分度不是很大時需要考慮建立聯合索引來提高查詢效率

繼續閱讀