hash小讲
一、hash算法的基本思路
1.直接寻址法
取关键字或者其某个线性函数值为散列地址
2.数字分析法
分析数据后找出数字的规律进行构造
3.平方取中法
取关键字平方后的中间几位作为散列地址
4.折叠法
将关键字分割成位数相同的几部分,然后取这几部分的叠加和
5.随机数法
选择随机函数,取关键字的随机值
6.除留余数法
取关键字被某个不大于散列表长度的数p除后所得的余数,也可以与以上几种方法一起使用即先处理关键字再取余。一般p为素数。
二、具体的实现
MD5
- 填充输入信息长度使其=N*512+448
- 用64位记录填充之前信息长度,现在信息总长度变为(N+1)*512即512的倍数
- 装入四个幻数
- 把消息以512位为分组进行处理,每个分组进行4轮变换,第一组以四个幻数为起始变量,其余组以上一组的输出为变量,最后一组的输出即为MD5值
SHA
java Hashcode
Object.hashcode()
java默认实现的hashcode方法,是native方法,其实现原理是用对象的内存地址得到hash值
String
String对象的hash在刚创建时:
- 如果是由别的String拷贝而来,则将hash值赋值为拷贝对象的hash
- 否则,初始为0,延迟到使用hashCode函数时再进行计算
hashCode 的计算:
value中所有字符的加权值之和,每个字符的权值为$31^{index}$,index是字符在字符串中的下标
private char value[];
private int hash;
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
Integer等包装类
hashcode就是其封装值的值
数组
首先对数组中的数据类型进行判断,根据其类型进行调用
public static int hashCode(Object obj) {
if (obj == null) {
return 0;
}
final Class<?> clazz = obj.getClass();
if (!clazz.isArray()) {//非数组直接返回hashcode
return obj.hashCode();
}
//获取数组的类型
final Class<?> componentType = clazz.getComponentType();
if (long.class.equals(componentType)) {
return Arrays.hashCode((long[]) obj);
} else if (int.class.equals(componentType)) {
return Arrays.hashCode((int[]) obj);
} else if (short.class.equals(componentType)) {
return Arrays.hashCode((short[]) obj);
} else if (char.class.equals(componentType)) {
return Arrays.hashCode((char[]) obj);
} else if (byte.class.equals(componentType)) {
return Arrays.hashCode((byte[]) obj);
} else if (boolean.class.equals(componentType)) {
return Arrays.hashCode((boolean[]) obj);
} else if (float.class.equals(componentType)) {
return Arrays.hashCode((float[]) obj);
} else if (double.class.equals(componentType)) {
return Arrays.hashCode((double[]) obj);
} else {
return Arrays.hashCode((Object[]) obj);
}
}
但实际上不同类型数组的hashcode计算都大同小异,都是数组中所有元素的加权和+$31{n}$,n是数组的长度,每个元素的权值为$31$,index是元素在数组中的下标
public static int hashCode(int a[]) {
if (a == null)
return 0;
int result = 1;
for (int element : a)
result = 31 * result + element;
return result;
}
在hashmap中如何使用
hashmap中对key的hash值的计算不是直接使用其hash值,而是使用其hash值和hash值的前16位的按位或
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
在计算位置时,会将取hash与(length-1) 的按位与
在这里有一个小tip,即hashmap的length始终是2的n次方,也就是说length-1始终是这样的结构:n个0与m个1,因此与hash按位与后的值实际上就是取hash的后m位
与此同时在hash值匹配后,还会使用equals函数检验是否相等。

浙公网安备 33010602011771号