博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数据结构笔记----哈希表及其在JAVA集合中的应用
阅读量:3907 次
发布时间:2019-05-23

本文共 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%4
在这里插入图片描述

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()也要被override hashcode不同,那么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散列查找的集合中时,我们就需要重写这两个方法

转载地址:http://sgqen.baihongyu.com/

你可能感兴趣的文章
软考相关英语
查看>>
[老老实实学WCF] 第四篇 初探通信--ChannelFactory
查看>>
ASP.NET 中的 Async/Await 简介
查看>>
解决Chrome中调试JS提示“Uncaught TypeError: Cannot use 'in' operator to search for”错误信息问题
查看>>
阿里巴巴java规范 第一版
查看>>
USB通信记事
查看>>
Android 编译(1)——Android编译步骤梳理
查看>>
编译器配置(1)——ARMv7,ARMv8(AArch64) 浮点配置等相关知识
查看>>
Android 编译(2)——jack-server相关问题
查看>>
网络服务(2)——以太网配置IPV4和IPV6
查看>>
网络服务(3)——以太网phy的识别加载(RK3399)
查看>>
网络服务(5)——usb网卡名称修改(RK3399 Ubuntu)
查看>>
行业观察与理解-互联网巨幕下各行业的现状和发展
查看>>
数据结构与算法大全
查看>>
稳定排序和不稳定排序
查看>>
句柄泄露与CloseHandle()
查看>>
一些笔记
查看>>
SVN的安装和使用
查看>>
APP测试点分析
查看>>
JDK安装过程中出现“javac不是内部或外部命令”问题的解决
查看>>