【转载】哈希表的原理,真的很难弄懂么?
【转载】哈希表的原理,真的很难弄懂么?
刘小爱v
发布时间:05-0909:06科技达人
转载路径:
https://baijiahao.baidu.com/s?id=1666172942887109917&wfr=spider&for=pc
以下为转载内容,原网站有较多方便理解的图
昨天学习了几种简单数据结构,为何要了解数据结构?一方面的原因是因为集合的底层就是与其息息相关的。
•ArrayList的底层数据结构:数组。
•LinkedList的底层数据结构:链表。
•TreeSet的底层数据结构:红黑树。
•HashSet的底层数据结构:哈希表。
前天学习了Collection集合,其继承体系图如下:
今天就来了解Collection的子接口List,Set,以及它们各自的实现类。
一、List接口
List,翻译就是列表的意思,列表有何特点?
•它的元素是有序的。
•它是有索引的(Collection没索引)。
•它的元素是可以重复的。
Collection是List的父接口,那么Collection中的所有方法,List都能直接拿来用。
List因为带索引,所以它相对于Collection的特有方法基本都是索引相关的。
集合
中有四类方法是最常见的:
也就是增加元素,删除元素,修改元素,查询元素,简称就是增删改查。
①增:add方法
可以直接添加元素,也可以根据索引添加元素。
②删:remove方法
Collection中的remove方法是删除对应的元素,List中可以根据索引来删除元素。
③改:set方法
修改对应索引位的元素。
④查:get方法
得到对应索引位的元素。
1.ArrayList
这个集合很早前就学习过了,因为太常见了。
ArrayList是List的实现类,看名字就能看出来,其中Array就是数组的意思,显而易见,ArrayList的底层就是数组。数组查询快,故ArrayList常用来查询数据。
那么问题来了,数组长度不可变,ArrayList怎么又可变了呢?
ArrayList默认是长度为10的数组,如果超过了,就会扩容。
如何扩容?
创建一个新的数组,再将旧数组复制进去,这样长度就增加了。
所以本质上ArrayList长度可变是因为底层换了数组。
2.LinkedList
和ArrayList一样,LinkedLIst也是List的实现类,其底层是链表。链表增删快,故LinkedList常用来增删数据。
集合中重要的是增删改查四种方法,linkedList有几种特殊的方法:
①addFirst方法:将元素添加到开头。
其中push方法和addFirst方法一样。
②addLast方法:将元素添加到结尾。
③removeFirst方法:将开头元素移除并返回。
其中pop方法和removeFirst方法一样。
④removeLast方法:将结尾元素移除并返回。
⑤getFirst方法:查询获取开头元素。
⑥getLast方法:查询获取结尾元素。
这几个方法都非常简单,理解其中文意思也就知道其作用了。
其中有两个方法比较特殊,官方解释如下:
•pop方法:从此列表所表示的堆栈处弹出一个元素。
•push方法:将元素推入此列表所表示的堆栈。
不要看它解释的这么复杂,其实就是堆栈结构,堆栈有什么特点?
先进先出,所以无论是增加还是删除,都是最上面的元素。
二、Set接口
Set和List一样,都是Collection的子接口。
特点和List刚好相反:
•它的元素是无序的。
•它是没有索引的。
•它的元素是不能重复的。
集合有没有索引的依据是什么?
如果元素可以重复,比如说一个集合存了两个元素,都是“刘小爱”,系统要如何判断它们?所以就需要索引,这样就能区分开:1索引位的刘小爱和2索引位的刘小爱,就算元素一样,索引也不一样。
故:元素可以重复,就有索引;元素不可以重复,就不需要索引。
Set因为没有索引,所以和父接口Collection的方法一样,没有特殊方法。
那如何保证元素不重复?这就得依赖于hashCode和equals方法。
1.Object类的hashCode(哈希值)
Object类有一个toString方法,代码如下:
toHexString:是转换成十六进制的意思。
也就是说,我们直接打印Object对象得到的一串地址值就是hashCode的十六进制。
但是一个对象它真正的地址值,Java是不会轻易告诉我们的,一是我们知道了也没啥用;二是黑客会拿它做坏事。于是Java就想了个办法,对真正的地址进行加密,也就是hashCode的由来。
所以什么叫hashCode?
hashCode是对真正的地址进行一种加密手段而得到的一串数字(什么手段也不用去了解,除非你要去做黑客)。
那么现在问题来了,有没有可能存在多个对象地址,对应同一个hashCode呢?
答案是有的,只不过这种情况非常少见。也就是说:
•不同的对象的真正地址是不可能相同的,
•不同对象的hashCode是有可能相同的。
如何理解这句话呢?
就是我们理论上是可以创建无数多个对象的,可以不停地在电脑上new对象,但是hashCode值是有限的,它是一个int类型的数据,最多也只有42亿(2的32次方)多种可能。
所以不同的对象是有可能出现同一hashCode的,这种情况就叫哈希碰撞,只不过遇到这种情况概率微乎其微。
Object有一个方法就是hashCode,按照继承的原则,所有类都有这个方法。
2.String的hashCode
String的hashCode方法是重写过了的,跟真正的地址其实是没关系的。
为何要这么做?为了保证Set的元素不可重复。
•hashCode值若是不相等,那这两个元素必定不重复。
•hashCode值若是相等,这两个元素大概率是重复的,但也有例外。
如下图几种情况:
三、哈希表
Set的元素不可重复,这个问题该如何解决?
若是我的话,我肯定会想:将新的元素和Set中的每一个元素比较一遍不就可以了?如果有相等的,就不添加;如果有不相等的,就添加。
这样做有问题么,理论上是没问题的,但是效率太低太低了,每次添加一个元素就要将元素遍历一遍。
那些程序员大神为了解决这个问题,就弄出了哈希表。
所以什么叫哈希表?
哈希表可以用来高效率解决元素不可重复这个问题,其本质就是:数组+链表+红黑树。
①哈希值就有点类似于数组中的索引,因为哈希值不同其元素必定不同。
数组查询快,如果现在添加进来了一个元素,我根本不用遍历,我就看有没有相同的哈希值(相当于索引),直接就可以定位:
•如果没有相同的哈希值,直接添加进集合。
•如果有相同的哈希值,我再比较内容是否一样。
数组有一个问题,就是长度是一定的,所以若是元素过多时,需要扩容。但是哈希表数据结构比较复杂,还要提前扩容:哈希表中数组默认长度16,如果数组中的元素超过了75%就开始扩容。
②虽然哈希值一样,但我还会比较它们的内容是否一样,用equals方法比较内容是否一样。
•如果内容也一样,重复元素,不添加进集合。
•如果内容不一样,不是重复元素,添加进集合。
③如果链表元素数量超过8,就将链表重构成红黑树。
链表查询是很慢的,所以为了查询效率,链表元素数量过多,就会重构成红黑树,红黑树查询效率比链表要快。
这里面涉及就到了两个方法:hashCode方法和equals方法,它们一起能很好地判断元素是否重复。
所以如果新建了一个对象,需要重写hashCode方法和equals方法,这个在开发工具中直接使用Alt+Insert自动重写方法。
HashSet的底层原理就是哈希表。
其中LinkedHashSet又是HashSet的一个子类,其特点主要是有序的Set集合,存储和取出的顺序一致。
【转载】哈希表的原理,真的很难弄懂么?相关推荐
- OSChina 周二乱弹 —— 球真的很难玩!
2019独角兽企业重金招聘Python工程师标准>>> Osc乱弹歌单(2018)请戳(这里) [今日歌曲] @clouddyy :推荐歌曲<Love Will Set You ...
- 转:Eric Lippert:阅读代码真的很难
转自:http://blog.jobbole.com/438/ 相关文章 微软资深软件工程师:阅读代码真的很难(第2篇) 阅读优秀代码是提高开发人员修为的一种捷径 学会阅读源代码 如何阅读大型代码库? ...
- 数据结构真的很难学?
如果你关注计算机专业招聘试题,会发现越是大型公司,问的问题越基础,有的甚至问你什么是栈和队列,反而一些小公司会关心你做过什么系统.从关注点的不同可以看出,大公司更注重基础扎实和发展潜力,而小公司希望你 ...
- 零基础学习java编程,真的很难吗?手把手将你带入编程世界。
零基础学习java真的很难吗?本人脑袋比较笨,从接触java到职业生涯已经小有4年了.怎么说呢,就是现在我依然能够保持着当年的那份不断学习的热情,是不是很不可思议.我告诉你,这是最基本最基础从事编程行 ...
- 民营企业的项目,真的很难做
民营企业的项目,真的很难做 笔者加入现在的项目超过2个月了.随着对于客户的了解越来越深入,尤其是通过合作的乙方咨询公司了解到一些情况,发现客户虽然越做越大越做越强了,但是却永远改变不了其民营企业的德性 ...
- 二本学校考211计算机,普通二本学校的学生考211/985的研究生真的很难吗?
原标题:普通二本学校的学生考211/985的研究生真的很难吗? 网友一: 我本科就是二本,念了一个交叉学科,交叉到什么地步呢,就是有些学校是把它放在教育学院,有些是设在物理学院,还有些是设在计算机学院 ...
- java左手画圆右手画方_左手画圆,右手画方真的很难吗?为什么人们很难做到呢?...
导语:左手画圆,右手画方真的很难吗?为什么人们很难做到呢? 我们经常会看到有些人能够实现左手画圆.右手画方的这一个行为,并且是可以通过这样的方式来训练自己身体的协调能力的,那么当我们自己去尝试的时候, ...
- (资源)百度云盘:驴火歌王:阅读真的很难提分第2讲:洞茶 (2013北京中考)
(资源)百度云盘:驴火歌王:阅读真的很难提分第2讲:洞茶 (2013北京中考)见上图 <祖逖>"天天练"(周六) 诸葛学堂<窦神归来文言文全年班>第 17 ...
- 女生学计算机真的难吗,女生想学计算机科学与技术,怕很难学懂,这门学科是不是特别难?女生学到底好不好?...
女生想学计算机科学与技术,怕很难学懂,这门学科是不是特别难?女生学到底好不好?以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下 ...
最新文章
- 关于树,各种平衡树查找树的资料合集~~
- 【机器视觉】 dev_update_var算子
- wordpress archive.php,哪个网址将导致wordpress使用archive.php?
- educoder 使用线程锁(lock)实现线程同步_线程间的通信(一)
- Sentinel(二)之Quick Start
- html表单中按钮添加超链接,JS 实现点击按钮实现超链接功能
- hpdl388安装2012系统_2010、2012型双端面中压釜用机械密封-安装指导
- java十次方项目链接 视频+资料+讲义
- android textwatcher 延时,Android TextWatcher监控EditText中的输入内容并限制其个数
- CVPR2021 最具创造力的那些工作成果!或许这就是计算机视觉的魅力!
- 文献整理和论文阅读方法
- 商务网站建设与维护【4】
- Linux - 自动同步网络时间
- 计算机网络知识点及例题总结(二)应用层
- css设置内容超出后显示省略号
- 详解Tensor用法
- 记录爬虫实战——有道翻译(反js加密)
- CVPR 2023 | 白翔团队提出:将CLIP模型用于场景文本检测
- 计算机打开共享网络连接打印机共享打印机,两台电脑如何共享打印机 多台电脑共享一台打印机设置方法【详细教程】...
- 更轻量的百度百舸,CCE Stack智算版发布
热门文章
- LeetCode Maximum Product Subarray(最大子数组乘积)
- LeetCode Pascal's Triangle
- CodeForces Gym-101350M
- 编译openwrt时报错:g++: internal compiler error: Killed (program cc1plus)
- gbdt xgboost 贼难理解!
- Ubuntu在终端执行命令时出现的错误
- python libnum库安装使用方法
- 【jQuery】选择器
- 如何解决Silverlight InitializeError #2103 - Invalid or malformed application: Check manifest
- 计算机没考好检讨,考试没考好检讨书范文(精选6篇)