本文共 1944 字,大约阅读时间需要 6 分钟。
在线性表和数表中,记录在表中的位置和记录的关键字之间存在不确定关系,他们的查找基于“比较”
而哈希表是根据关键字直接访问的数据结构 它是一种高效的数据结构,其高效主要体现在把数据的存储和查找时间大大降低,几乎可以看成是常数时间,而代价是消耗比较多的内存,然而在硬件技术越来越发达的今天,用空间换时间的做法在某种意义上是值得的。另外,编码比较容易也是它的特点之一。把关键词映成该关键字对应地址的函数,记为:Hash(key)=Address
常见的散列函数: (1)直接定址 Hash(key)=a*key+b(适用于关键字分布基本连续,不会产生冲突) (2)除留余数:Hash(key)=key%p(p为最接近表长M的一个质数) (3)数字分析:取关键字中分布较均匀的若干位作为散列地址 (4)平方取中:取关键字的平方值的中间几位作为散列地址 (5)折叠:将关键字分割成位数相同的几部分,将这几部分叠加作为散列地址开放定址法:
设增量为d,表示从冲突位置向后找第d个单元 (1)线性探测:如果冲突了,向后找到第一个空的单元,存入数据(d=0,1,2,3,。。。) (2)平方探测:如果冲突了,依次查看(这个单元往前数第N^2 个单元和往后数第N^2个单元)(N=0,1,2,3,…),直到找到空的单元 (d=0,-1,1,-4,4,-9,9,。。。。) (3)再散列法(双散列法):对增量使用哈希函数进行映射(d = hash2(key)) 拉链法(用于插入和删除频繁的情况) 如果hash函数计算结果相同,但关键字不同,就把记录用线性链表连接起来。 还需建立一个头指针链表,用于存放标识 例如哈希函数是hash(key)=key%4public boolean equals(Object obj) | public int hashCode() |
---|---|
用来判断其他的对象是否和该对象相等 ,String 、Math、Integer、Double等这些封装类在使用equals()方法时,会重写object类的equals()方法 | hashCode()方法给对象返回一个hash code值。这个方法被用于hash tables |
性质:自反,传递,一致,对称 | 相等(相同)的对象必须具有相等的哈希码(或者散列码),但是如果两个对象的hashCode相同,它们并不一定相同。 |
当equals()方法被override时,hashCode()也要被override | hashcode不同,那么equals肯定也不同,反过来则不一定(有些时候equals方法被重写后不再比较地址,而是比较内容) |
要弄明白hashCode的作用,必须要先知道Java中的集合。
总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。 这里就引出一个问题:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢? 这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。 于是,Java采用了哈希表的原理。 这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。有时在我们的业务系统中判断对象时有时候需要的不是一种严格意义上的相等,而是一种业务上的对象相等。在这种情况下,原生的equals方法就不能满足我们的需求了.
Object类中定义的equals()方法是用来比较两个引用所指向的对象的内存地址是否一致.并不是比较两个对象的属性值是否一致当我们自定义的一个类,想要把它的实例保存在以Hash散列查找的集合中时,我们就需要重写这两个方法
转载地址:http://sgqen.baihongyu.com/