定義注意點:java
hash函數
來完成,hash函數
是hash表的核心與難點。對於整數,能夠將取模運算
做爲hash函數
。靜態、動態
),這也是名稱中"表"的含義。思考角度,當空間無限時,可使用O(1)完成各項操做,當空間只要1個時,就退化爲線性表O(n)。git
對於不一樣的關鍵字獲得了同一個hash地址,這種現象稱爲hash衝突(collision),形式化爲:
key1≠key2,f(key1)==f(key2)
,其中f
爲hash函數。github
一致性:若是a==b
,則hash(a)==hash(b)
,這是java自定義類時必須需重寫的hashcode方法
緣由。算法
高效性:計算高效便捷,O(1),這也是使用動態數組,在適當的狀況下resize的緣由。編程
均勻性:哈希值的分佈越均勻越好,這就是取模法中模爲質數的緣由。數組
hashcode=val%M
,其中M爲一個質數,M的參考取值請點擊這兒。注意,公式總val
爲正整數,若是類型爲int
,能夠先進行去除符號操做:val=val&ox7fffffff
。由於從二進制的角度看ox7fffffff
就是0和31個1,正好把符號位過濾掉。ide
code=c*26^3+o*26^2+d*26^1+e*26^0
abcd=a*B^3+b*B^2+c*B^1+d*B^0
,進製表示的形式簡化以及編程實現:函數
hash(code)=(
c*B^3+o*B^2+d*B^1+e*B^0
)%M,能夠表示爲每一位乘以base,在加下一位測試=
((((c*B+o)*B+d)*B+e)%M
,很重要,在java字符串的hashcode方法中B=31this=
((((c%M)*B+o)%M*B+d)%M*B+e)%M
,取餘操做能夠拿到括號裏面去。(此性質快速冪算法中很經常使用)
int hash=0; for(int i=0;i<s.length;i++){ hash=(hash*B+s.charAt(i))%M; } //java中B的是31,不在意是否溢出,只要返回的是一個整數就OK,不知道M是什麼,因此就沒有出現M。
日期類型:考慮每一個部分,每部分表示不一樣的權重(進制思惟)。
hash(date)=(((date.year%M)*B+date.month%M)*B+date.day)%M
類:分別將類的每個字段當作B進制中的某一位。依據B進制數進行轉換。
1.由於默認的hashcode()方法取對象的地址爲基礎得到的,而new()同一類的不一樣實例對象地址不一樣,使得hashcode的結果也不一樣,這就不知足一致性,例如,new Person("小明")兩次,它們的hashcode不一樣,但這顯然就不合理。
2.重寫hashcode()只是爲了得到正確的hash值,但當衝突了,還須要逐個字段進行比較才能肯定是否相等,這就要求重寫equal來完成,由於默認的equal就等於==
,含義爲比較對象地址。
基本思路利用已有基本類型的包裝類和String類的hashcode()
方法來生成咱們的hashcode()
public class Student { Integer grade; Integer cls; String name; //省去無關代碼 @Override public int hashCode() {//套路:模仿String,Base取31 int B=31; int hash=0; hash=hash*B+grade.hashCode(); hash=hash*B+cls.hashCode(); hash=hash*B+name.hashCode(); return hash; } @Override public boolean equals(Object obj) {//有套路,逐個字段比較 if(this==obj) return true; if(obj==null)return false; if(this.getClass()!=obj.getClass()) return false; Student another=(Student) obj; return this.grade.equals(another.grade) && this.cls.equals(another.cls) && this.name.equals(another.name);//字符串比較相等,equals } }
完整代碼以及測試用例,請點擊這兒。
數組中每一個元素保留的是地址。數組中每一個元素的位置是N%M
去掉符號位:hashcode(k1)&0X7FFFFFFF
動態空間(擴容和縮容)處理N/M>=upperTol
和N/M<lowerTol
都是先得到key索引,而後再獲某個元素。TreeMap<K,V> map=hashtable[hash(key)]
。
完整源碼及測試代碼請點擊這兒。