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便是用了哈希表法查找。