数据结构笔记----哈希表及其在JAVA集合中的应用

哈希表(散列表)的基本概念

在线性表和数表中,记录在表中的位置和记录的关键字之间存在不确定关系,他们的查找基于“比较”
而哈希表是根据关键字直接访问的数据结构
它是一种高效的数据结构,其高效主要体现在把数据的存储和查找时间大大降低,几乎可以看成是常数时间,而代价是消耗比较多的内存,然而在硬件技术越来越发达的今天,用空间换时间的做法在某种意义上是值得的。另外,编码比较容易也是它的特点之一。

散列函数

把关键词映成该关键字对应地址的函数,记为: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%4
在这里插入图片描述

equal和hashcode详解

参考博客:最详细的equal和hashcode详解
java.lang.Object类中有两个非常重要的方法:

public boolean equals(Object obj)public int hashCode()
用来判断其他的对象是否和该对象相等 ,String 、Math、Integer、Double等这些封装类在使用equals()方法时,会重写object类的equals()方法hashCode()方法给对象返回一个hash code值。这个方法被用于hash tables
性质:自反,传递,一致,对称相等(相同)的对象必须具有相等的哈希码(或者散列码),但是如果两个对象的hashCode相同,它们并不一定相同。
当equals()方法被override时,hashCode()也要被overridehashcode不同,那么equals肯定也不同,反过来则不一定(有些时候equals方法被重写后不再比较地址,而是比较内容)

要弄明白hashCode的作用,必须要先知道Java中的集合。  
总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。
这里就引出一个问题:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?
这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。
于是,Java采用了哈希表的原理。
这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。

我们为什么需要重写hashCode()方法和equals()方法?

有时在我们的业务系统中判断对象时有时候需要的不是一种严格意义上的相等,而是一种业务上的对象相等。在这种情况下,原生的equals方法就不能满足我们的需求了.
Object类中定义的equals()方法是用来比较两个引用所指向的对象的内存地址是否一致.并不是比较两个对象的属性值是否一致

在什么情况下需要重写hashCode()方法和equals()方法?

当我们自定义的一个类,想要把它的实例保存在以Hash散列查找的集合中时,我们就需要重写这两个方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值