同一个字符串hash值相同吗_深入理解Hash和hashCode的应用

822025b6764b65db3369ed58484c9d5f.png

经常写程序的人都会听说或看到Hash,或者叫散列,或者叫哈希,它们是一个东西。

Hash是指把任意长度的内容,根据已有的转化规则,得到相同长度的一串内容,可以看成一个黑箱子,无论从左边进去多少长度或者多么复杂的内容,出来后永远是固定长度的一串字符串。

这个黑箱子就是哈希算法。

看起来有点像概括提取内容,事实上也确实如此。

值得注意的一点:不同的内容有可能生成一样的Hash Code,但是不同的Hash Code必然对应不同的内容。

如果能理解上面这句话,你就理解了什么是Hash。也就是说Hash只能从已知内容获得一串固定的Hash Code,但不能从一串固定的Hash Code反推已知内容,所以Hash Code和已知内容之间不是简单的key-value一一对应关系。

关于Hash算法,常见的有SHA1、SHA256、MD5、TIGER等等,它们采用不同的一些算法来实现这个功能,不同的Hash算法得到的结果也不一定相同,但是同一个Hash算法对指定内容的结果必须相同。

比如程序中常用的密码存储常采用MD5算法。用户在注册的时候,输入明文密码串,但是数据库存储的并不是这一串明文密码,而是经过MD5算法转换的固定长度字符串。用户在登录的时候,重新输入明文密码,在验证的时候,对该明文进行MD5算法转化,然后再与数据库的密码进行比较,来确定用户身份。

这样做的好处就是防止明文密码泄露,如果是明文存储,那么一旦数据库发生泄露或者被人意外看见,很容易就可以堂而皇之地进行账号登录,非常不安全。目前的App或者网站设计中,一般已经很少见到明文存储的密码数据库了,如果有,那黑客可能非常喜欢。

另外在数据传输领域,Hash也可以很好地用来快速检验数据丢包的问题,在数据发送前把数据内容进行Hash计算并把这个值一并传给接收方,同时在接受方同样对数据内容进行Hash计算,如果两边Hash值不一致,就能知道数据在传输过程中发生了错误。

在程序中Hash也经常使用,有一定开发经验的人肯定重写过hashCode函数,这个hashCode()方法,产生的是对象的Hash值,在Java中如果使用了散列集合,比如HashMap、HashSet、HashTable等等,在插入的时候,都会调用hashCode()并获得这个对象的Hash值作为一个主键。

另外,如果重写hashCode()一般都要和equals方法一起重写,源码注释里是这样写的:同样的对象,必须生产同样的hashCode,而equals就是用来比较对象是否相同,因此,这两个函数方法是强相关的。

这里举一个开发中遇到的例子,kotlin中有data class和普通的class,根据文档介绍,其中data class默认生成了copy()、equals() 、hashCode()、toString()等函数。值得注意的是,这个默认的hashCode()和class中的默认的hashCode()并不完全相同。data class中重写的equals是值比较,而class中默认的equals是引用比较,所以当data class中的值发生变化时,hashCode()会相应地变化,而class中的hashCode()保持不变。

首先我们看一下data class的表现

object 

输出结果如下

0
31
2


其次,我们再看一下普通class的表现

object 

输出结果如下

2054798982
2054798982
1

而如果我们重写普通class类的hashCode函数

object 

输出结果如下

0
31
2

通过这个小实验,大家应该能对Hash和hashCode有了一个初步的理解了吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值