前面将到了Base64,再谈下Hash。
Hash平时接触最多的就是HashMap,熟悉HashMap里的人应该知道,其本质是一个数组,对key进行哈希运算后,会得到一个数组下标,根据下标来保持数据,也正是因为这样HashMap才能做到取数据O(1)的时间负责度。
简单点说,Hash就是把任意数据转换成指定⼤⼩范围(通常很⼩,例如 256 字节以内)的数据。实质是对原始数据的有损压缩,损失到什么程度呢,压缩后的书记,仅能用作原始数据的唯一标识。
那Hash的意义在哪?
前面讲到非对称加密中私钥加签时,是通过对原始数据做的加签的到,显然对于非对称加密来说,原始数据的大小和加签后数据大小基本一致,那么假如我需要对一部4G的电影加签后网络传输,难道还要传输8个G这么多?所以,对Hash值进行加签,让公钥持有方自行用同样的算法对原始数据计算Hash值后,再进行验签。
换一个说法,Hash也可以看成是一个人的特征标识,通过一系列的特征标识,可以标识这个人是谁,比如说我们的身份证号,某种程度上就是对我们自己进行了一次Hash,通过身份证号来证明自己。
再说个面试中经常问的,为什么重写了equals()方法,都需要重写hashCode()?
先看下Object里equals()源码:
public boolean equals(Object obj) {
return (this == obj);
}
方法很简单,就是比较两个对象内存地址是否一致。可见,Java默认是认为,两个对象地址一致的话,就是同一个对象。hashcode()虽然不一定返回和内存地址有关的信息(与JVM厂家的实现有关),但是他们的都满足一个约定:
- 一致性(consistent),在程序的一次执行过程中,对同一个对象必须一致地返回同一个整数。
- 如果两个对象通过equals(Object)比较,结果相等,那么对这两个对象分别调用hashCode方法应该产生相同的整数结果。(PS:这里equals和hashCode说的都是Object类)
- 如果两个对象通过java.lang.Object.equals(java.lang.Ojbect)比较,结果不相等,不必保证对这两个对象分别调用hashCode也返回两个不相同的整数。
所以最初Object的equals()和hashcode()可以理解成有关的,自然,一旦修改equals()方法,那么完全由可能出现equals()一致,但是hashcode()不一致的情况,这样在HashMap这里数据结构里,虽然你认为两个对象是一致的,但在HashMap还是会占两个槽。