Hashtable
1 注意小写 table
2 常用方法
void clear()
boolean contains(Object value) //作用等于containsValue(Object value)
//在HashMap中已经不存在
boolean containsKey(Object key)
boolean containsValue(Object value)
Set<Entry<K, V>> entrySet()
boolean equals(Object object)
V get(Object key)
int hashCode() //返回此map的哈希值
boolean isEmpty()
Set<K> keySet()
V put(K key, V value)
V remove(Object key)
其中hashcode是重写的方法这里给出Java® Platform, Standard Edition & Java Development Kit Version 12 API Specification关于abstractmap的hashcode方法的解释
详见
https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/util/AbstractMap.html#hashCode()
返回这个map的hash码的值
map的hash码 定义为 这个map的entrySet()的每一个键值对的hash码的和
这确保了对于map m1以及m2 m1.equals(m2) 即为 m1.hashCode()==m2.hashCode()
正如Object.hashCode()的常规协定
简单来说就是返回这个map的地址 因为对于每一个map m1 m2这个值都是相同的,那这
个就可以作为类的地址,
可以看出 返回值就是entryset的和
简单介绍hash (散列)
hash 是一种压缩映射 把任意长度的输入 通过算法变成固定长度的输出 输出值即为hash值 算法即为某种hash算法
散列值的空间远小于输入空间 但是不同的输入可能会产生相同的输出 即碰撞 hash算法需要对碰撞进行处理
简单介绍 常用hash算法
1直接寻址法 取关键字的线性函数生成散列地址H(key)=a *key+b;
2 数字分析法 分析数据,找出数字规律,尽可能利用数据构造重估纪律较低的散列地址,例如员工生日,年月冲突较大,而月日冲突的情况明显减少
3平方取中法 关键字平方后取其中几位 作为散列地址
4 折叠法 将关键字分割成位数相同的几部分,各部分相加,作为散列地址
5 随机数法 取关键字作为随机数种子生成随机数作为散列地址
6 除数留余 H(key)=key%p p一般取素数或者奇数 减少碰撞
简单介绍 处理冲突的方法
1 开放寻址法 Hi=(H(key) + di) MOD m i=1,2,3,… d[i]是数列 就是第i次产生碰撞探测增量序列,有常见三种取法
1 di=1,2,3,4,… 很容易理解 一个地址被占用继续使用下一个地址 称为线性探测再散列
2 di=1^2,-1^2,2^2,-2^2,…+-k^2 只是另一种产生新地址的方法 成为二次探测再散列
3 di=伪随机数序列 称为随即探测再散列
2 再散列法 Hi=RHi(key),i=1,2,… 不同的散列函数,其中RHi为产生碰撞,使用另一个散列函数重新计算
3 链地址法 就是每一次产生碰撞,使用同一个散列地址,让碰撞输入指向前一个输入
4 建立公共溢出区 每一次产生碰撞 就是用溢出区的地址
回到这个问题
计算机存储数据的地址很长很复杂,通过hash算法,得到hash地址,根据这个例子我们map中的元素较少,hashcode也会比较小,但是元素不同,hashcode不同,而返回值也确实与具体的map有关,所以在api中的介绍,并没有用对象的地址作为定义,而是用了每一个键值对的hash码的和,这样的说法,因为并不是创建map时产生的hashcode,而是每次增减删改元素时,其hashcode都会变化
这里只介绍java语言的语法中关于hashcode()方法的简单体感,以及背后的数学模型,逻辑实现,并不打算继续深入介绍底层实现,有兴趣可以去学习微机原理,计算机硬件的物理实现,等相关课程。
3 HashMap和Hashtable几乎等价 区别在于
0 作者不同
Hashtable Arthur van Hoff Josh Bloch Neal Gafter
HashMap 多了Doug Lea 道格·利 JSR-166是来自于Doug编写的util.concurrent包。jsr 即Java Specification Requests(java语法标准)著有Concurrent Programming in Java: Design Principles and Patterns
Arthur van Hoff 最早任职于Sun Microsystems公司,从事java程序语言的早期开发工作,设计并实现jdk1.0的许多方面,java编译器,java调试器,许多java类以及hotjava浏览器
Neal Gafter是Java SE 4和5的主要设计者,参与了78,曾是c++标准委员会的一员,领导开发c++编译器
Josh Bloch 为领导了众多Java平台特性的设计和实现,其中包括Java Collection框架、java.math包以及assert机制。著有 Effective Java 一书。
产生时间
Hashtable是java一开始发布就提供的键值映射的数据结构
HashMap产生于JDK1.2,已经成为应用广泛的一种数据类型
1 HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null;而Hashtable则不行
2 HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,在单线程环境下它比HashMap要慢。而java5以上需要线程安全时,可以使用ConcurrentHashMap
3 遍历方式的内部实现上不同
4 初始容量大小和每次扩充容量大小的不同
Hashtable默认的初始大小为11,之后每次扩充,容量变为原来的2n+1。HashMap默认的初始化大小为16。之后每次扩充,容量变为原来的2倍。Hashtable和HashMap设计时的侧重点不同。Hashtable的侧重点是哈希的结果更加均匀,使得哈希冲突减少。而HashMap则更加关注hash的计算效率问题。
5 计算元素的位置的方法不同
hashtable是利用对象的hashcode用除留余
hashmap则是进行位运算