基礎知識回顧
哈希算法
因爲Java的HashMap源碼裏面有個混淆函數hash(),我就想補一下哈希的定義。
哈希算法有以下三個特點
- 安全,給定數據 M 容易算出哈希值 X ,而給定 X 不能算出 M ,或者說哈希算法應該是一個單向算法。
- 兩個不同的數據,要擁有不相同的哈希。
- 長度固定,給定一種哈希算法,不管輸入是多大的數據,輸出長度都是固定的。
仔細想一下,如果哈希的長度是固定的,也就是取值範圍是有限的,而輸入數據的取值範圍是無限的,所以總會找到兩個不同的輸入擁有相同的哈希。所以,哈希函數的安全性肯定是個相對概念。如果出現了兩個不同輸入有相同輸出的情況,就叫碰撞,collision 。不同的哈希算法,哈希位數越多,也就基本意味着安全級別越高,或者說它的”抗碰撞性“就越好。
位的操作
- 正數的反碼=原碼=補碼
- 負數的反碼爲符號位保持不變,其餘各位取反
- 負數的補碼就是在補碼的基礎上+1
邏輯運算符
- >>>: 無符號右移
按二進制形式把所有的數字向右移動對應位數,低位移出(捨棄),高位的空位補零。對於正數來說和帶符號右移相同,對於負數來說不同。
其他結構和>>相似。
- ^ : 位異或
0^0=0, 1^0=1, 0^1=1, 1^1=0
- | : 或運算
0|0=0, 0|1=1, 1|0=1, 1|1=1
- & : 與運算
0&0=0, 0&1=0, 1&0=0, 1&1=1
- ~ : 非運算
~1=0, ~0=1
B樹 和 B+樹
B+樹主要底部的葉子節點,和相連的節點有鏈接指向的關係。回去還得翻一翻以前的Sqlserver的索引的知識。
HashMap的實現原理
源代碼主要通過數組+鏈表實現的,數組就是常說的桶,只是桶裏裝的是“糖葫蘆”式的鏈表,還是樹結構的數據。
hash()方法
這個擾動函數就是解決哈希出現相同key值的hash輸入的可能性。
- 獲取key自帶的hashCode
- h再進行無符號向右移動16位,也就是取h的高16位
- 這樣的話自己的高半區和低半區做異或,就是爲了混合原始哈希碼的高位和低位,以此來加大低位的隨機性。
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}