之前写过两篇关于hashcode()作用的文章,现在看来是非常片面的。
知乎的一个问题什么是哈希算法?里面有一个ID叫蒋又新的用户说的给了我很多启发,虽然我不完全认同的他的观点,特别是——这个HASH算法不是大学里数据结构课里那个HASH表的算法——这句话。
还有一个ID为Cascade的用户说的很透彻。
hash算法是一个摘要算法,给一个数据A获取一个数据B,B是A的指纹,它从某种程度上“描述”了A。指纹数据一般都是整型数据。
hash算法有很多应用,在密码学领域有MD5 SHA1等,当然他们不只用于密码,很多时候它用于辨识信息是否被篡改过;而在编程领域它还可以用在快速存取上,也就是Hash表。
哈希算法将任意长度的二进制值映射为较短的固定长度的二进制值,这个小的二进制值称为哈希值。哈希值是一段数据唯一且极其紧凑的数值表示形式。如果散列一段明文而且哪怕只更改该段落的一个字母,随后的哈希都将产生不同的值。要找到散列为同一个值的两个不同的输入,在计算上是不可能的,所以数据的哈希值可以检验数据的完整性。一般用于快速查找和加密算法
——《数据结构与算法分析》
.
哈希算法并不是一个特定的算法而是一类算法的统称。哈希算法也叫散列算法,一般来说满足这样的关系:f(data)=key,输入任意长度的data数据,经过哈希算法处理后输出一个定长的数据key。同时这个过程是不可逆的,无法由key逆推出data。
快速查找的应用就是——Hash表,而加密算法的应用就是——单向函数。当然了hash函数应该说是单向函数的一种逼近。这里帖一个文章,原贴已经找不到了。http://zhaohaolin.iteye.com/blog/1874420
场景一:
如果你只有两个对象(包含多条数据的集合),你想比较他们,那你肯定用不着hash算法,但是如果你有20,000个对象,当你新拿来一个对象想看看这20,000个对象里面有没有跟他重复的那你就要循环比较20000次,挨个进行比较,再或者你想在这20000个数据中剔除掉重复的,如果迭代进行比较那就有的忙了。而如果有一个算法可以根据你的对象内部的多个数据生成一个新的数据(“指纹”),然后你只需要比较这个新的数据那工作就立马变的简单了。
场景二:
比如百度云盘——人们把文件上传上云盘中。但其实很多文件是重复的,什么MP3之类的,基本就是那么相同的几个。服务器没有必要重复存储这么多信息。一个合理的方式是,当用户上传一个文件时,给文件一个哈希码。当另一个用户上传同一个文件时,先在服务器查有无这个哈希码,如果有,用户就不用上传了,这就是所谓妙传技术,有时候几百M的文件,瞬间就上传完毕就是这个道理。
场景三:
密码的使用,可能大家都看过谍战片,电报以密文形式传输,https也是密文传输,这是一种既可以加密也可以解密的加密方式,一旦被敌人知道了密钥就会被破解。不要侷限于这种加密方式。还有一种加密方式,在特定条件下有用,比如登录密码。我们设定登录密码的初衷并非为了告知别人我的密码内容是什么,那么我们的密码就可以使用不可以解密的方式被加密,假如我设置了密码abc,它被加密成为xyz(f(abc)=xyz),在我登录的时候系统不需要解密xyz,而是要求我再次输入可以被加密为xyz的密码。
场景一就是快速存取,场景二是信息摘要,场景三是加密。他们都利用了hash算法,只是依赖的特点不同。一、二依赖的是他碰撞小的特点,三依赖的是他不可逆、碰撞小的特点。
java中hashcode()方法就是产生一个对象的指纹数据,这个指纹数据有比较小的可能性会发生碰撞,这时候就只能通过equals方法来进行判断了。
而hashcode()方法的应用就是在hashmap和hashtable了。
需要额外说明的一点就是hashmap和hashtable使用hashcode的时候,只有key在使用,跟不同的key值我们计算得出它的hashcode,然后利用数组的快速存储特点进行存取,发生碰撞的情况才使用链表进行存取;而value的值是自定义的,与hash完全没有关系。