00:00
大家好,我是海波老师,咱们继续来讲Java集合中的哈希map,那么我们之前呢,给大家提了一下哈希map底层当中是如何存储数据的,我们这里呢,再把这个过程呢,我们再简单的描述一下来,首先首先呢,我们先把这个呢,我们给它调一下顺序啊,咱们调下顺序来,把这个放到前面去,好放到过来以后,大家看一下,我首先是这个A1呀,这个A1呢,我们先给它干嘛呀,把我们的数据往里面存,往里面存的时候记住了同学们这里呢,是根据我这个A来算出来,我到底应该存到哪里去,那比方说我的A1呢,就存在了什么我的这个位置啊,是靠这个A来算出来的。那么这个时候没有任何的问题,对不对,但是呢,我放A2的时候就有问题了,因为我们A2当中的这个K啊,它的A跟这个A是完全相等的,相等的情况下就会发现有一个是一,有个是二,那么我第二个这个值就会把第一个值给它覆盖掉,这个能不能明白我说的意思,就是说如果当前相同的key,它的那个后面的V呀,会把前面的V给它覆盖掉,但是你要记住你覆盖的同时是可以把那个旧的值给我得到的,然后呢,现在呢,我的C3我们过来了,C3过来了以后大家可以看到,诶,通过哈希运算,它可能定位到哪去了呢?哎,我的这个二的地方,所以啊,就把它一放放就可以了。
01:18
那么然后呢,我们再把这个第四呢,我们再给它往里面放,往里面放的时候,你会发现它同样做哈希计算,但是我这个D啊,它巧了,跟这个C怎么了一样了。他们俩去的是同一个位置,这是完全有可能的呀,哎,老师,那不对呀,你们俩不相等啊,你没有办法把它覆盖掉啊,对了,你不相等,你没有办法覆盖掉,这就跟咱们前面讲哈希set一样,咱们用链表的结构把它连在一块儿对不对?所以啊,我们就可以想办法把它们连在一起不就行了吗?同学们,我们用这种方式就可以了。老师,那如果来一个,我们叫什么呢?叫做我们的这个东西叫做一,咱们叫做五呢,嗯。比方说我们写成它啊,咱们叫做E5怎么样,如果咱们现在得到的是E5的话,咱们也往里面放,同学们往里面放,往里面放完了巧了怎么了也跟它相同的怎么办?那不用说了,咱们依次呢,往下加不就完事了吗?所以啊,咱们还是形成链表的结构,这里给大家讲一讲就可以了,但是这个跟咱们前面讲的那个叫link的list有点不太一样,为什么呢?因为咱们那个link的list呀,它的那个列表啊,是两边可以互相加什么呢?它从first可以往后加,它从last可以往前加,这个咱们其实说过吧,但是呢,我们这个链表呢,它只有一个方向,就意味着它只能从这往下这么去做,它不能反过头来找到它往前走不行,所以这个链表呢,我们称之为什么呢?我们叫做单向链表,这个咱们说一下,它称之为叫单向链表啊,就是一个方向是吧,所谓的单向呢,就是我们一个方向的意思,这个大家能不能明白,所以啊,咱们哈希map的底层数据结构啊,它其实用的是。
02:59
的速度,再加上我们的单向链表,单向链表啊,它的这个方向呢,只有一个,所以我的数据越集越多,越集越多,那么查询起来就会非常的慢,效率非常的低,所以啊,我们的JDK呢,为了解决这个问题呢,它提供了一种特殊的结构叫红黑二叉树,这个呢就不在本期视频中做讲解了,大家可以看我们上硅谷发布的完整版的Java教学视频,好了,把这个流程呢,我们大概的说了一下以后,我们回过头来,我们再给大家讲解一下它的基本操作方式,所以把它关掉。
03:29
关掉以后呢,我们来拷贝,拷贝以后呢,我们写上一个下划线一啊,咱们点击OK,点击完成以后,我们把这个咱们全都去掉啊,全去掉,去掉以后呢,把这个呢,我们也去掉就行了,接下来往里面放数据,往里面放数据的时候,同学们我们的put的方法没有任何的问题,我们往里面放数据时候,我写上一个A,我再写上一个逗号一,这个是对的,但是同学们记住了,我这个po的方法咱们讲过了,它往里面放数据是没问题的,如果我们没有找到相同的数据,它就是一个新增的感觉,所以啊,它就是我们添加数据的意思,但是呢,如果我发现这个A呀,在这个map里面已经存在了,其实它就是我们修改数据的感觉,所以我们的这个方法呀,其实它是有返回值的,这个返回值我们来写上它VR回车这个值啊,就是我们旧的那个值,如果你当前是修改的话,那么它就是旧的值,A老师呀,那如果我第一回添加这个值有没有呢?所以咱们打印一下。
04:29
来把这个旧的值咱们打印一下,哎,放过来,放过来以后,同学们,我运行一下,你观察结果,你会发现我第一回往里面放,它没有旧的值,它返回的结果就是个空啊,就是这个意思,但是呢,如果你再来复制,复制了以后大家看一看,来我们在这里呢,给它来啊,我们再加一个拷贝,拷贝以后大家看一下,放到这边我给它一个零,行了,我给个零之后,大家会发现这是我的第一个值,这是我们添加的第二个值,但是因为这两个K是完全相同的,所以呢,它就等同于修改数据了,把零变成了一,那你把零变成了一,你的零不就是那个旧的值了吗?所以我打印的结果呢,它应该是我的零,大家观察一下应该是对的,你看零不就出来了吗?
05:16
其实啊,除了这个方法以外,我们还有一个方法叫map点我们有一个叫put if abset啊有这个方法,这个方法是什么意思呢?这个方法呢,我们给他一个B,我们给他一个我们的二,什么意思啊,还是往里面放数据,所以还是添加数据,诶老师这个铺的方法不就添加数据吗?怎么又多了一个方法呢?诶咱们看看啊,添加运行以后看结果,你会发现我们当诶这个看不出来是吧,我忘了把这个地方给它来了,诶放过来,我们把这个map呢给它放进去,然后呢,我们点击运行,运行以后看结果,大家观察一下,AA1 B2,诶没问题啊,这是有什么区别呢?咱们再给大家放一个,大家观察一下什么呢?我放一个B3,廖老师。
06:01
你要这么放的话,他这里不就被覆盖掉了吗?我们来运行一下看结果。运行以后看结果,它那个B3出来了吗?没有,现在大家想想什么意思?很简单,就是说如果呀,你往里面放的时候,里面不存在,那好我就会把这个B放进去,但是如果它里面已经有数据了,我就不能往里面放了啊,为什么呢?因为如果你放不就覆盖掉了吗?所以啊,我们这个方法是在干这个事情,如果你没有我就添加,如果你有我就什么都不做,懂我的意思吗?同学们就是这个方法了。那好了,那这个咱们有了以后,咱们再说另外一个方法叫做修改方法,诶老师你不说这个put的方法就能修改吗?其实还有另外一个方法叫做map,点我们叫replace,这个方法呢,就可以把我们的B给它修改成我们的四,你这么写就行了,它就可以直接把咱们的key呢,修成我们指定的这个值,没有任何的问题,然后呢,我们来看看,我们点一下我们VR回车,回车以后它也会返回一个值,所以把这个做掉,做掉以后把这个拿过来啊,然后呢,把这个呢写上它,嗯,放过来,放过来以后呢,同学们,我们现在运行一下,看效果运行。
07:10
运行以后看看结果,你会发现我们当前的这个值是不是变成了我的B4了,大家会发现我们是不是把之前的那个二打印出来了,哎,就是这样啊,所以它返回的也是我修改之后的那个值,老师呀,那如果我要没有找到这个值怎么办?比方说我写上一个C。我写上一个C的话,这里没有啊,你没有的话,这个四能不能放进去呢?我再运行,运行以后看结果,你会发现我们当前根本就没有所谓的C吧,所以这个方法才是真正的一个替换和修改的方法,而这个破的方法就比较特殊了,它那个修改这个数据啊,纯粹是一个特殊情况,而我这里呢,才是真正的替换修改的意思,为什么呢?因为如果你没有的话,我根本就不会修改吧,而我的put你没有的话,是不是就添加进去了?哎,所以啊,不同的方法它的作用是不一样的。好了,同学们,我们再来我们的map.clear它的clear呢,顾名思义就是清空啊,把我当前map集合中的数据我们都清空掉,是不是就可以了,也没有任何的问题啊,哎,老师啊,你不说了吗?咱们的map可以有大量的对key的操作,对V的操作,那么它都有什么样的操作呢?其实我们来给大家演示演示啊,把前面的我们都给它做掉,咱们简单一点啊,来,嗯,我这里这么写吧,把这个清空,然后呢,Map点我们的put,然后呢写上它,咱们就叫做张三。
08:29
然后呢,写上一个我们的一好了,来,然后写上一个李四啊,写上后面的王五行了,这里的我的二和三就有了啊有了二和三之后,现在干嘛呢?我的map,我们这里呢,点有一个叫key set,什么意思啊,同学们,顾名思义啊,他把我的key啊全取出来,当成了一个集合,来,我们点一下VR回车,你现在的这个set里面放的就是我所有的key,所以呢,我们说一下,诶,我们就获取我们map集合中所有的key啊,所有的key,诶老师为什么是set呀,还记得吗?咱们set结果描述了一个什么样的集合。
09:11
是不是数据不能重复呀,所以你能明白这个的话,咱们map中的那个key它也不能允许重复,对吧?这个我相信大家都能明白,所以啊,咱们这个呢,就可以这么做了,诶老师,那我取数据的话,我这样的话可不可以挨个遍利把每个key取出来呢?其实你想想我们的site点一下我们的for循环,不就是把每个key就取出来了吗?你把每个key取出来的话,那么我的map点我们的key不也就能够执行了吗?所以啊,我们去打印一下来,咱们写上它,嗯,咱们叫做打印好了,那我现在我运行一下,你会发现我的key和V我就都能够拿得到了,没有问题啊,咱们的213哎就可以了啊。那我现在是对这个key操作呀,其实我们再来map点,大家会发现我还有一个叫做判断,判断我当前的map集合里面有没有指定的key,比方说叫张三,那不用说了,咱这里肯定有啊,对不对,所以呢,它返回的结果应该是个true啊,那如果没有的话,返回的结果应该就是一个false了,所以给他打印,哎,就是这样好了,我运行一下这里肯定是处啊,因为咱们有张三啊,所以咱们的结果肯定是处,没有任何的问题。
10:21
那好,这是对我们的key的操作,其实我们再来,我们写上叫map点,它有个叫values,这个values顾名思义啊,就是把我所有的value给它取到,所以VR回车,回车以后它得到的就是个collection集合,那好了,它如果是个集合的情况下,我对它做便利也没有任何的问题,对吧?循环遍历嘛,诶除了这个以外,它也有对应的map点,我们叫contain,我们的value,你会发现我们的包含某个值也没问题啊,你这里写上我们的这个什么呢?我们的一也是完全可行的,哎,就是这个道理,哎,老师啊,你这么写我觉得倒也是没有什么太大的问题啊,但是我们之前老说建职队,建职队,我在这个地方也没看见所谓的建职队啊。
11:06
哎,这里给大家讲一下,我们现在给大家演示的这些方法呢,其实是把T和V给它独立开的,但是如果你真正想获取那个所谓的键值,对的话,我们也有方法,所以把前面的这些咱们全注掉,哎,这个别注掉了,我们往下啊来想想看。我们叫做什么呢?我们写上叫todo,叫获取我们的键值对对象,那么这里呢,我们就写上它了,叫map,它有一个方法叫什么呢?叫entry site这个方法,这个方法叫entry,其实就是一个元素的意思,它就是我们map当中的一个元素,而这个元素呢,其实就是我们的键子对,所以我们点开我们给一个VAR回车,回车以后它是一个S。哎,老师,这个赛为什么感觉不出来它是一个键字,对呢,你确实感觉不出来,那是因为我们现在啊,没有增加泛型就会导致呢,你看的不是很明显,我们之前不是讲过泛型的概念吗?所以我们可以在map的这个地方,我们增加一个兼括号,然后呢,传递一个字符串,然后呢传递另外一个字符串,这两个字符串啊,一个是用来约束那个key的类型,一个是用来约束那个value的类型,所以你现在把它去掉,你重新来一遍,我们叫map,点我们叫ENT site好了,回车以后你看一看,你观察一下有没有发现这个set也带着我们当前的什么泛型了吧,这个就叫entry。
12:27
这个安垂呢,是我们map当中的一个内部的一个接口类,所以呢,也就意味着我现在得到的其实就是安垂,好了,那我就遍利一下呗,所以把这个我们的安垂来拷贝,拷贝以后我们点一下,咱们叫负循环,诶增强负循环,增强for循环,我得到的就是每一个安垂了,所以呢,我们来打印它,我们直接来打印它就可以了,打印以后我们观察一下运行,运行以后看结果,你会发现我们当前张三等于一,李四等于二,王五等于三,这不就是成对出现吗?如果你想获取它的某一个key呀,或者value都行,所以咱们点一下来,我们写上叫点R,它就有一个叫get key,同样道理,我们再来,我们写上等号,再写上加号,我们叫entry,我们叫做点get value,这个也没有任何的问题啊,我们再来运行一下。
13:16
运行之后咱们看结果就可以了啊好了,同学们,我们现在这个跟刚才是完全一样的啊,这样的话就可以获取数据了,好了,接下来呢,我们再来说一下我们的这个蕊木方法啊,咱们map点我们的这个瑞木,诶好了,那么这个蕊木当中啊,你会发现我们之前呢,就给大家说了,我们可以传一个张三进去,对不对,现在呢,我们给他来啊,咱们这个助调助掉以后,我们现在运行,运行以后,诶不对,我这个忘了打印了啊,把这个去掉,去掉以后呢,把这个map呢,我们打印一下来,我们写上一个map,现在呢,我们来打印一下。打印之后大家看结果,你会发现李四和王五没有任何的问题,但是呢,我们除了这个方法以外,还有一个方法。咱们叫map.remove他有一个这个方法,他传一个key和一个V说一下我就不知道什么意思了,我给他一个张三,我给他一个什么呢?我们的11111,好了,我这么写完了以后,现在呢,我运行一下看看结果。
14:15
运行以后看结果,诶同学们,你会发现我们当前的这个蕊木好像怎么了,张三没删掉啊。哎,老师为什么没删掉,很简单,因为它删除的是一个特定的KV键值,对,就意味着只有当张三等于它的时候才会被删掉,所以我写上一个一,我再去运行,运行以后看结果,这个时候你就会发现我们的张三就没有了吧,所以啊,刚才这个瑞木啊是不考虑Y6的,而这个蕊木呢,是要考虑Y6的啊,把它们两个都相等了才能够删除,而这个只要K相等就能删除,所以啊,咱们的方法其实不太一样啊,好了,除了这几个方法以外,包括咱们前面讲的什么map呀,点size呀,包括map.is呀,就这些方法呢,其实都有很多啊,包括我们的什么可粒啊,这个其实都是有的,包括什么map点克隆啊,对吧,它其实都有啊,还是那句话,我们这里呢,就不给大家一个一个展示了啊,因为这些方法还是比较好理解的,反正呢,都是比较常用的方法了,这个大家下来呢,自己写一写,试一试,应该问题不大啊,行了,哈希map的常用方法咱们就讲到这里。
我来说两句