Java中哈希表(Hashtable)是如何实现的

Hashtable中有一个内部类Entry,用来保存单元数据,我们用来构建哈希表的每一个数据是Entry的一个实例。假设我们保存下面一组数据,第一列作为key, 第二列作为value。

{“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方法的源码如下:

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;
... ...
}

这样数据存储到哈希表之后,当我们要查找或者说获取一个对象时候,采用同样的方式可以快速的找到我们需要的对象。

哈希表可以快速的找到一个元素。在有大量的数据的时候,比普通的顺序查找要快的多。

假设有10000条数据,如果采用顺序查找,最坏的情况下需要对比10000次能找到,最好的情况是1次。平均查找次数位(10000+1)/2,大约为5000次。

换一种方式,如果把10000条数据通过hash值索引分成10组,每一组有1000条数据,这样每一次只需要先确定是哪一组,然后在1000条数据里查找,这样最坏的情况是1000次, 最好的情况是1次。平均查找次数为(1000+1)/2 ,大约为500次。比上面的方法快了5倍。

我们常用的5种算法有顺序查找,二分法查找,二叉排序树查找,哈希表法查找,分块查找。Java的Hashtable即是用了哈希表法查找。

最新文章

  1. Web测试介绍2一 安全测试
  2. [LeetCode] Design Tic-Tac-Toe 设计井字棋游戏
  3. Protocols
  4. sql返回两个日期之间的日期_函数实现
  5. ENode 1.0 - 框架的物理部署思路
  6. Microsoft.Owin.Security.OAuth搭建OAuth2.0授权服务端
  7. #笔记#JavaScript进阶篇二
  8. M面经Prepare: Find integer Average of 2 integers.
  9. js获取IP地址方法总结_转
  10. PLSQL_性能优化系列07_Oracle Parse Bind Variables解析绑定变量
  11. Core Bluetooth Programming Guide
  12. Swift基本语法及与OC比较之二
  13. FileUpload 改变控件显示的文字
  14. MFC自绘控件学习总结
  15. C++ Primer 学习笔记_79_模板与泛型编程 --模板编译模型
  16. php 中文转拼音首字母问题
  17. 将MPLS编译进linux内核中
  18. Android --&gt; 常见控件
  19. 举例让抽象问题具体化:包含min函数的栈
  20. 适合初学者的python实际例子

热门文章

  1. Median Weight Bead(最短路—floyed传递闭包)
  2. lintcode-31-数组划分
  3. Print之modile, level
  4. 枚举当前环境中打开的所有IE
  5. Windows下BMP位图格式介绍
  6. RT-thread内核之异常与中断
  7. Luogu1053 NOIP2005篝火晚会
  8. 【以前的空间】poj 2288 Islands and Bridges
  9. BZOJ4567:[SCOI2016]背单词——题解
  10. UVA.455 Periodic Strings(字符串的最小周期)