Java中哈希表(Hashtable)是如何实现的
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即是用了哈希表法查找。
Java中哈希表(Hashtable)是如何实现的的更多相关文章
- C#中哈希表(HashTable)的用法详解以及和Dictionary比较
1. 哈希表(HashTable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似keyvalue的键值对, ...
- 转 C#中哈希表(HashTable)的用法详解
看了一遍有关哈希表的文字,作者总结的真是不错 .收藏起来 1. 哈希表(HashTable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提 ...
- C#中哈希表(HashTable)的用法详解
描述: 哈希表存放 key.values ,key值可以用于快速调取用,values 对应object类型,也就是说所有类型. 实例: 1.HashTable存放学生的成绩 Hashtable ht1 ...
- java集合-哈希表HashTable
一.简介 HashTable也是一种key-value结构,key-value不允许null,并且这个类的几乎全部的方法都加上了synchronized锁,来保证并发安全,由于加了锁所以性能方面会比较 ...
- [转]net中哈希表的使用 Hashtable
本文转自:http://www.cnblogs.com/gsk99/archive/2011/08/28/2155988.html 以下是PetShop中DBHelper中的使用过程: //创建哈希表 ...
- 哈希表(hashtable)的javascript简单实现
javascript中没有像c#,java那样的哈希表(hashtable)的实现.在js中,object属性的实现就是hash表,因此只要在object上封装点方法,简单的使用obejct管理属性的 ...
- 哈希表(Hashtable)简述
一,哈希表(Hashtable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似keyvalue的键值对,其中 ...
- c/c++ 哈希表 hashtable
c/c++ 哈希表 hashtable 概念:用key去查找value 实现hash函数有很多方法,本文用除留余数法. 除留余数法的概念: 取一个固定的基数的余数,注意不能用偶数,用偶数的话,分布会不 ...
- js中哈希表的几种用法总结
本篇文章只要是对js中哈希表的几种用法进行了总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助 1. <html> <head> <script type=" ...
随机推荐
- holoeverywhere修改actionbar背景
<style name="Holo.Theme.Light.MyActionBar" parent="Holo.Base.Theme.Light.DarkActio ...
- LintCode-12.带最小值操作的栈
带最小值操作的栈 实现一个带有取最小值min方法的栈,min方法将返回当前栈中的最小值. 你实现的栈将支持push,pop 和 min 操作,所有操作要求都在O(1)时间内完成. 注意事项 如果堆栈中 ...
- iOS-获取webView的高度
- (void)webViewDidFinishLoad:(UIWebView *)wb{ //方法1 CGFloat documentWidth = [[wb stringByEvaluatingJ ...
- 3ds Max学习日记(一)
暑假闲来无事学习一发3ds Max.为啥要学这玩意?貌似可以用这东西三维建模.暑期生产实习选了一个搞vr的导师,貌似他忙得很,无奈只好先自己研究一下啦~ vr神马的还是有点意思的,虽然自己仅仅 ...
- Perfmon - 脚本自动监控
PerfMon-Windows性能监视器是个好东西,可以辅助我们分析发生问题时间段服务器资源占用情况,但是部署性能计数器确实一个相当麻烦的事情,往往这种枯燥的事别人还做不了,只能由我们这些希望获取到P ...
- mstsc远程登录终端超出最大连接数的解决办法
1,.远程服务器有两个用户登录 2.第三个登录时提示:终端服务器超出了最大允许连接,这种情况怎么解决 A.通过运行命令来解决:运行输入mstsc /admin /v:IP:端口 敲回车来解决,这里的 ...
- vue-cli项目里npm安装使用elementUI
第一步:进入到项目目录里 npm i element-ui -S 第二步:在main.js中引入 import ElementUI from 'element-ui' import 'element- ...
- C#中的is和as操作符
在C#语言中进行类型转换的操作符is和as.is和as都是强制类型转换,但这两者有什么相同之处和不同之处呢?在使用is和as需要注意哪些事项?下面我们从简单的代码示例去探讨这个简单的问题.注:此博文只 ...
- 线程同步(使用了synchronized)和线程通讯(使用了wait,notify)
线程同步 什么是线程同步? 当使用多个线程来访问同一个数据时,非常容易出现线程安全问题(比如多个线程都在操作同一数据导致数据不一致),所以我们用同步机制来解决这些问题. 实现同步机制有两个方法:1.同 ...
- 【Maven】Snapshot和Release版本的区别
Snapshot版本代表不稳定.尚处于开发中的版本,快照版本. Release版本则代表稳定的版本,发行版本. 什么时候用Snapshot版本? 依赖库中的jar正处于开发的阶段,会被经常被更新,这种 ...