1. 理解hash
我们怎么理解hash,散列函数——是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。 百度上的定义,只说了操作,没有体现这么做的目的 。
我说一下我的通俗理解:哈希算法根据自身的特点得出一个散列值,根据这个值,我们可以在存储中直接取得所要的记录,不需要依次比较,这样对应的加工函数,就是hash。
我们需要查找的对象经过hash之后,都会集中放在一个表里面,通俗一点,由此而来的形成的一个表就是HashTable
我们如果的哈希函数设计的好的话,在我们的需要存储对象域中每一个对象都有有自己的对应的唯一值,那么在表中查找的速度会很快,但是没有那么完美的哈希函数,不免会发送碰撞 ,就是明明对象是两个不同的东西,hash之后hash值是一样的,这种情况是允许的,但要尽可能的不出现,不然就损失了我们定了hash函数的初衷。
下面举一个例子吧来帮助我们大家理解,假设现在有10个房间编号1-10,现在我们有一把钥匙,因为其他的信息什么都没有提供,我们只能一扇一扇的门去试,去看看这把钥匙能不能打开其中任何一扇门,这样的效率是低下的,于是你就拿着钥匙去问房间的管家,管家通过看钥匙的特征,告诉你这是5号门的钥匙,而hash函数就是这个将钥匙特征转换成编号的管家
2. equals方法和==的区别
- ==我们知道是比较计算机中的物理地址,但是equals()是怎么样的呢?我们先来看看源码
public boolean equals(Object obj) {
return (this == obj);
}
java里面默认的equals()方法就是比较两个对象的地址,在计算机中我们都知道就算是同一个对象new出来两个对象他们equals()都是false,但是官方的定义希望不是这样的,它希望在对象之间应该是比较对象的属性,如果属性都相同,我们就能认为是相同的,因此在java的内置对象中都进行了重写,下面展示一段代码,大家可以从这里面体会
public class Demo4 {
public static void main(String[] args) {
String a = "123456";
String b = "123456";
System.out.println(a == b);
int c = 1;
Integer d = 1;
System.out.println(c==d);
// Integer就重写了equals方法
Employee e = new Employee(18,"xxxx",75000.0);
Employee w = new Employee(18,"xxxx",75000.0);
System.out.println(e.equals(w));
// 自定义对象没有重写equals方法
}
}
运行结果如下
true
true
false
所以我们在自定义对象的时候最好是重写equals方法,让其不能是比较物理地址
3. hashcode()和 equals()
在java中默认hashcode是根据物理地址生成的一个hash值,这个hash值在java中HashSet或者HashMap中起着提高查找效率的作用,这里的HashMap就类似于HashTable,在HashSet中,equals()相不相等是判断是否重复元素的标准。