Java中哈希表(Hashtable)是如何實現的html
Hashtable中有一個內部類Entry,用來保存單元數據,咱們用來構建哈希表的每個數據是Entry的一個實例。假設咱們保存下面一組數據,第一列做爲key, 第二列做爲value。java
{「one", 1} {"two", 2} {"three", 3} {"four", 4}
寫一個演示程序:算法
import java.util.Hashtable; public class Main { public static void main(String[] args) { Hashtable<String, Integer> numbers = new Hashtable<String, Integer>(); numbers.put("one", 1); numbers.put("two", 2); numbers.put("three", 3); numbers.put("four", 4); numbers.put("five", 5); Integer n = numbers.get("two"); Integer nn = numbers.get("six"); if(n != null) System.out.println(n); System.out.println(nn); } }
Hashtable內部用一個Entry數組table,來保存全部的數據。數組
當咱們插入一個新的Entry對象時,即用Hashtable的put(key, value)方法。
在put方法裏:
計算key的hash值
計算index值,做爲數組table的下標,即table[index]
哈希表中根據key的索引值index,建立了多個bucket,全部index值同樣的Entry對象,構形成一個連接表存放在同一個bucket裏。既然是一個連接表,根據數據結構知識,天然咱們的Entry對象須要有一個指向下一個對象的指針,即Entry對象須要有這些屬性:key,value,next。數據結構
如何構造hash函數?函數
hash值,如何生成?對於每一個對象的hash值,要保證每個hash值都不同。
在Java SDK中, String的hashCode方法以下:指針
//hash的初始值爲0 public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }
index值,如何生成?這裏要求保存的數據是均勻的分配在每個bucket中,Hashtable源碼中採用%操做(mod)使數據分佈在編號爲0~10的bucket中。
Hashtable中put方法的源碼以下:code
private int hash(Object k) { // hashSeed will be zero if alternative hashing is disabled. return hashSeed ^ k.hashCode(); } public synchronized V put(K key, V value) { ... ... int hash = hash(key); int index = (hash & 0x7FFFFFFF) % tab.length; ... ... }
這樣數據存儲到哈希表以後,當咱們要查找或者說獲取一個對象時候,採用一樣的方式能夠快速的找到咱們須要的對象。htm
哈希表能夠快速的找到一個元素。在有大量的數據的時候,比普通的順序查找要快的多。
假設有10000條數據,若是採用順序查找,最壞的狀況下須要對比10000次能找到,最好的狀況是1次。平均查找次數位(10000+1)/2,大約爲5000次。
換一種方式,若是把10000條數據經過hash值索引分紅10組,每一組有1000條數據,這樣每一次只須要先肯定是哪一組,而後在1000條數據裏查找,這樣最壞的狀況是1000次, 最好的狀況是1次。平均查找次數爲(1000+1)/2 ,大約爲500次。比上面的方法快了5倍。對象
咱們經常使用的5種算法有順序查找,二分法查找,二叉排序樹查找,哈希表法查找,分塊查找。Java的Hashtable便是用了哈希表法查找。