Hash算法,及HashMap使用

简介: 为什么要Hash? 哈希表是基于数组实现的,哈希算法就是如何将键值(key)转换成数组小标的方法,哈希化可以提供非常高的操作(插入、删除、查询)效率,因为对有序数组的查询,即使是二分查找也只能做到O(logN),因为哈希可以直接将要查询的key转化为数组小标,所以可以达到O(1)的时间级。 Hash算法:将key做hash后的值叫hashcode,hashcode的值范围可能很大,

为什么要Hash?

哈希表是基于数组实现的,哈希算法就是如何将键值(key)转换成数组小标的方法,哈希化可以提供非常高的操作(插入、删除、查询)效率,因为对有序数组的查询,即使是二分查找也只能做到O(logN),因为哈希可以直接将要查询的key转化为数组小标,所以可以达到O(1)的时间级。


Hash算法:将key做hash后的值叫hashcode,hashcode的值范围可能很大,Hash算法是将一个较大范围的hashcode转换为定长的区间的数值。一个好的hash算法应该使hashcode均匀分布在区间内。 但是难免还是会有不同的key会产生相同的hashcode,此为哈希冲突。

例如,要对公司100个雇员的信息做哈希存储,要求以姓名作为键值,“frank” 的hashcode是3135416,如果直接用3135416做小标,意味着要用一个非常大的数组,显然非常浪费。mod是最简单,往往也是最有效的hash算法,3135416%100=16,这样就可以用array[16]来存储“frank”的信息了。


如何解决哈希冲突?

  1. 开放定址法
    线性探测,二次探测,再哈希。
    例如“leo”的hashcode是733616,用模100哈希算法后,其值也是16,因为array[16]已经被占用了,产生了“冲突”,那么顺序查看16的下个位置17,看array[17]是否可用,如果可以则存储leo,否则继续探测下个位置18,直到有空位为止。在查询时,若一个key的哈希值为16,不能就简单的返回array[16],因为哈希值为16的可能是frank 或者 leo,所以还要比对key值。
  2. 链地址法
    Java 的 HashMap就是用LinkedList解决hash冲突的。

参考:http://en.wikipedia.org/wiki/Hash_function


使用Java HashMap时,注意以下几点:

1. HashMap不是线程安全的

不要在并发环境中使用HashMap,这样会造成不可预期的后果,据sun的说法,在扩容时,会引起链表的闭环,在get元素时,就会无限循环,后果是cpu100%。

如果Concurrent is a must,请用Map m = Collections.synchronizedMap(new HashMap(...))

2.如果数据大小是固定的,那么最好给HashMap设定一个合理的容量值

因为HashMap的默认容量是Capacity(16) * LoadFactor(0.75) = 12,如果你的HashMap是用来装载1万条数据的,那么HashMap会不断的扩容(resize),而每次扩容都会对原有数据做重新排列,非常的time-consuming,所以应该在初始化HashMap的时候用New HashMap(15000),负载因子(loadFactor)用默认的0.75就好了。

More about loadFactor:这个loadFactor有做什么用得呢? 是用来减少collision的,试想一下, 是不是越接近满载的时候,产生冲突的可能性越大呢,就像公交车上有16个座位,此时上来5个人,几乎不会出现抢位子的情况,因为很空。假如又上来10个人,那么15个人对16个座位,可能有些人觉得前面座位比较好,就会产生冲突并问候对方的父母。现在规定这个16座的公交车只允许载客12人,也就是负载因子是0.75,后面来的人用另一辆空车装载,这样就可以有效的解决冲突。

3.成为HashMap的key的条件

HashMap是用一个数组Entry[ ]来存储相应的Entry<K, V>的,所以在put(K, V)操作时,首先检查Key的hashCode,看该Entry在数组中是否已经存在,若不存在,加到数组中,否则,会再将K.equals()于现有已存在数组中得Entry的链表(linked list)中的K进行比较,若有相同的,将其替换, 若没有,将该Entry置于链表的头部。

在get( )操作是,是先查看HashCode,再比较equals,两者皆匹配的时候,才会返回Value。

所以这是为什么要作为HashMap的key要override hashCode 和 equals的原因。

参考:http://www.iteye.com/topic/754887

4. HashMap 和 HashTable, HashSet的比较

1.Hashtable是Dictionary的子类,HashMap是Map接口的一个实现类;
2.Hashtable 中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。
3.HashMap 允许key和value为null,HashTable则不允许
4. HashTable直接用对象的hashCode,HashMap有自己的hash算法
5. HashSet不是Map是Set,其与ArrayList的区别是HashSet不允许重复元素,可通过HashMap.keySet()获得HashMap中key的set

发现一个对hash深入研究的博文,以及用hash做Top K 问题的solution (有1000万条(查询串)记录,找出里面top 10出现次数最多的查询串的方法)

http://blog.csdn.net/v_july_v/article/details/6256463


目录
相关文章
|
2月前
|
存储 缓存 负载均衡
一致性 Hash 算法 Hash 环发生偏移怎么解决
一致性 Hash 算法 Hash 环发生偏移怎么解决
91 1
|
6月前
|
设计模式 算法 Java
面试官:JDK1.8 HashMap扩容rehash算法是如何优化的?
本文跟大家聊一聊一个常见的面试题,那就是JDK1.8 HashMap扩容rehash算法是如何优化的?
|
3月前
|
算法 数据可视化 数据处理
Algorithms_算法专项_Hash算法的原理&哈希冲突的解决办法
Algorithms_算法专项_Hash算法的原理&哈希冲突的解决办法
19 0
|
4月前
|
存储 算法 索引
Python 数据结构和算法:什么是散列表(Hash Table)?在 Python 中如何实现?
Python 数据结构和算法:什么是散列表(Hash Table)?在 Python 中如何实现?
|
6月前
|
算法
29MyCat - 分片规则(固定分片hash算法)
29MyCat - 分片规则(固定分片hash算法)
22 0
|
6月前
|
存储 缓存 算法
数据结构与算法第十六讲:分布式算法之一致性Hash算法
数据结构与算法第十六讲:分布式算法之一致性Hash算法
|
7月前
|
存储 负载均衡 算法
一致性hash算法深入探究
一致性hash算法深入探究
43 0
|
7月前
|
算法 C# 流计算
MD5、SHA256等Hash算法的实时计算
MD5、SHA256等Hash算法的实时计算
|
8月前
|
算法 Unix 数据安全/隐私保护
常见的hash算法及其原理?
常见的hash算法及其原理?
|
8月前
|
存储 算法 安全
走进Python Hash函数的魔幻世界:解密哈希算法与防碰撞技术
走进Python Hash函数的魔幻世界:解密哈希算法与防碰撞技术
105 0