最近看了下张老师有关HashCode的视频,现将内容记录如下:
如果想查找一个集合中是否包含某个对象,大概的程序代码怎么写呢?你通常是逐一取出每一元素与要查找的对象进行比较,当发现某个元素与要查找的对象进行Equals方法比较的结果相等时,则停止继续查找并返回肯定的信息,否则,返回否定的信息。如果一个集合中有很多元素,比如一万个,并且没有包含你要查找的对象时,则意味着你的程序要从该集合取出一万个元素逐一比较之后才能得到结论。有人发明了一种哈希算法来提高从集合中查找元素的效率,这种方式将集合分成若干个区域,每个对象可以计算出一个哈希码,可以将哈希码分组,每组分别对应某个存储区域,根据一个对象的哈希码就可以确定该对象存储在哪个区域。 HashSet就是采用哈希算法存取对象的集合,它内部采用对某个数字n进行取余的方式对哈希码进行分组和划分对象的存储区域。Object类中定义了一个hashCode()方法来返回每个Java对象的哈希码,当从HashSet集合查找某个对象时,Java系统首先调用对象的hashCode()方法获得该对象的哈希码,然后根据哈希码找到相应的存储区域,最后取出该存储区域的每个元素与改该对象进行Equals方法比较,这样不用遍历集合中的所有元素就可以得到结论。可见,HashSet集合具有良好的对象检索性能,但是,HashSet集合存储对象的效率相对要低些,因为向HashSet集合中添加一个对象时,要先计算出对象的哈希码和根据这个哈希码确定该对象在集合中的存放位置。
为了保证一个类的实例对象能在HashSet正常存储,要求这个类的两个实例对象用equals()方法比较结果相等时,它们的哈希码也必须相等。也就是说,如果obj1.equals(obj2)的结果为true,那么以下表达式的结果也要为true:obj1.hashCode()==obj2.hashCode()。如果一个类的hashCode()方法没有遵循上述要求,那么,当这个类的两个实例对象用equals()方法比较的结果相等时,它们本来应该无法被同时存储进Set集合中,但是,如果将它们存储进HashSet集合中时,由于它们返回的hashCode()的返回值不同,第二个对象首先按哈希码计算可能会被放进与第一个对象不同的区域中,这样,它就不可能与第二个对象进行equals方法比较了,也就可能被存储进HashSet集合中了。Object的hashCode()方法不能满足对象被存入到hashSet中的要求,因为它们的返回值是根据内存地址推算出来的,同一个对象在程序运行期间的任何时候返回的哈希值都是不变的。所以,只要是两个不同的实例对象,即使它们的equals方法比较结果相等,它们默认的hashCode()方法返回的哈希值也是不同的。