00:00
好,下面呢,我们来看下这个map接口,哎,这个mapb接口的话呢,是我们并列于collection的一个接口,它呢用来存储的叫双列数据,对,或者叫一对就是数据啊,那么我们看下这个它的一个集成数结构,哈希的话呢,这里边涉及到的时间类呢稍微多一些,呃,首先呢叫哈希map,关于map啊,它的实现类稍微多一些,首先呢是哈希map,其次呢叫link,哈希map是它的子类,然后呢,诶,Tree map tree map呢是先实现了一个接口,这个接口呢又是map的子接口啊,你看这个接口我们就能暴露出来,说这个map呢是一个有序的。哎,咱们前边呢那个呃吹side其实也是一样啊,那么还有的话呢,有一个类叫哈西table,这个要特别小心的就是这个T在我一篇里边,这个T呢是小写的。按说应该是大写的啊,你看这时候它还不太满足我们说的标识符的这个命运规则啊,规则规范这块,然后呢,它的一个子类呢,叫properties,所以说呢,我们这呢,关于它的时间类,一个两个三个四个五个稍微多一些,那首先呢,我们关注一下这个map,它的这个时现类的一些特点,就像前面我们讲a release的link list和vector一样啊,哎,这块我们去新建一个,哎,在这下边首先我们整一个这个包啊,叫Java啊,这些呢我们就都关掉了,在这个下边呢,我们去新建一个关于这个map的一个测试啊,我们叫map的一个test,嗯,那首先的话呢,我们就关于这个map这个框架结构,它的这些实现类做一个说明。
01:39
那首先呢,提到我们这个map接口,前面呢也讲过了,它呢存储的我们叫做呃双列数据,相较于我们的collection叫单列数据来讲,双列数据那么用于存储。啊,存储具有这个KY6这个特点的啊,啊,我们叫做间值对的这个数据,那前面呢,我们也稍微提过它呢,这个类似于咱们呢,诶高中讲的函数,这个函数的概念啊,函数呢就是Y等于FX,其实的话呢,跟它的要求其实确实都一样啊,咱们一会儿呢展开来说啊,那这是关于map这个接口的一个说明,它下边呢,有具体的一些视线类,那我们这块呢,就分别来解释一下,首先呢,看到一个叫哈希map,这是一个哈希map呢,它有一个子类link的哈希map。
02:35
类似于前面set中的子类link的哈set一样,然后哈希map的话呢,这块并列的啊,我们再写个叫吹,哎哎,Tree map,然后下边呢,还在并列着写一个哈西table t是小写的哈table呢有一个子类叫properties。好,这呢就是它的这样的一些实现类,那首先呢,我们分别说一下每一个实现类的一些特点,这个呢是大家要关注的map,咱们这一章当中map和list是重点啊,Set的话呢,重要性就差一些了,那首先哈map我们先写谁呢?关于它和这个哈table的一个对比着去写。
03:19
啊,为啥呢?呃,他们两个呢,相当于有这种类似的这种替代关系了,有点像前面讲的aist和vector一样啊,有点像他俩的关系啊,也就是说哈希map呢,它呢是作为咱们map的一个主要实现类,没有特别的情况,大家基本上想用一个map,那就选哈希map就行。啊,那对应的我们的哈table啊,它呢,作为一个古老的实现类,那什么叫古老,这个咱们前面讲vector时候也提到过这个事情,步伐呢,我们也看一下ctrl c ctrl shift t啊哈希table它在1.0的时候就有了,然后ctrl shift t,哈希map,哈希map呢,啊这跑到这来了,马上找我们这个类。
04:08
它呢,在1.2的时候呢,才有的啊,然后呢,这个map呢,点开也是1.2的时候才有的啊ctrl shift t啊link啊哈map。啊,也是啊,这个另个I map出来更晚啊,它在1.4的时候呢才有,那么ctrl shift t再看一个map map这个接口也是在1.2的时候呢才有。嗯,他们每一个结构什么时候出现的,这个我们就能捋清楚回过来,首先在1.0的时候呢,先有一个叫哈希table,用这个呢来去存储这种建值对特点的数据,有点类似于前面的vector啊,用着挺好。然后呢,用到1.2的时候呢,说不想用了,此时呢,我们出来一个新的接口,叫做map啊,用这个接口来规范存储键值这特点的数据,然后呢,紧接着提供了这个map的一个主要实现类,叫哈希map。
05:05
同样的啊,存储这种有序的这种键呢,我们也出现了一个叫map啊,这两个呢就出来了啊,如果你不需要有序,通常我们都用它,然后在用这个过程当中发现呢,诶,我们在做一些便利操作的时候呢,发现它的效率呢,稍微偏差一点,诶我们又出现了个叫link的哈西,Map在1.4的时候呢出现的。啊,其实呢,从这个1.2出现的时候呢,就决定了这个哈希贴呢,后边就不怎么用了啊,作为一个古老的时间类,原因是什么,还是在于同步的问题啊,那么哈新map呢,它是一个线程对不安全的啊,那对应的就是效率高啊,跟咱们前面的a release和vector一样,线程安全,哎,效率低。哎,那这块呢,我们也很容易的去看到,像哈西table当中啊,我们呢,看它的一些这个方法的时候,你看synchronized synchized的这个呢,这个就判断有没有,他没有对这个本身的核心数据进行修改,所以就没有加这个啊synchized了,只要呢,涉及到这个数据的一些修改的等等的啊,诶都会有,这个叫C空袋这样的一个操作,行,这呢是我们看到它有同步,那你去哈希table步里边,呃,哈希map里边去看的就没有了。
06:26
诶,Table里边就有行,这呢就关于这个线程安全不安全的一个问题,那还有一个小的区别就是哈西map呢,它是可以存储对这个nod。啊,No的这个key和value的啊,就是这个key或者是value是no,我们去往里添加是OK的,而我们这个哈,Table呢是不能诶存储no key或者是value的。哎,这是一个小的知识点啊,不妨呢,咱们说到这呢,就简单做一个测试,诶,Public VO,我们就TEST1啊简单的我们测一下,这呢,我们就生命成一个map吧,啊然后右边呢,我们去new一个。
07:10
哎,首先呢,我用一个呢叫哈希map。好,这呢就造好了,这个map的话呢,往里边放数据,它呢不叫ADD,对它叫put,那你就得放个key,放个value,那比如我们这个呢,哎,咱们现在不是演示这个nor嘛,我这写成个no,这写成个123,相当于咱们的K呢,就是一个nor,哎,我现在呢是new的哈西map看一下没有问题,不会报错,这个VALUE6的话呢,也可以是no,所以我就写两个no,比如说。你看都是可以的,那现在呢,咱们把这个map我在这个位置呢,给大家重新去扭一个,谁呢叫哈西table啊,你看这个table这个T是小写的,那在哈cable上,我们去put它,那这时候它就报一个控制人的异常了,就言IG呢,我们这个nod key或者VALUE6,比如说你这写个值,这个K呢,或者是value啊,只要有是no的哈西table当中都放不进去。
08:13
啊,这是这个点啊,那显然呢,从健壮性的角度来考虑,我们这个呢就不太好,就不太好,就是用户呢,如果没有去填key或value这个值,我们可以认为是个no,那no的时候呢,往哈tableable呢放不进去,这个不太好我们的哈map呢,这个健壮性就要更好一些,嗯,这就提到一个应用场景,比如说呢,大家在这个浏览器上,你会写这个你的基本信息,不管是注册或者登录啊,比如说登录吧,登录的话呢,你会写上你的这个name啊,你会写你这个PASSWORD2个文本框啊,你这块呢,把数据写进去,这有个登录一点这个按钮,数据呢就发过来了,这时候呢,这个数据实际上呢,就保存在map当中啊,就保存在map当中,那怎么保存呢?它有两个建设,对第一个建设对呢,它的key就叫做name。
09:05
啊,你的这个值呢,就是你填的这个名,第二呢,你这个password啊,冒号一下就是你填的这个密码啊,这就是两个减值,对,那么我们就用这个map存的,你在后台这块呢,可以获取这个指定K对应的value啊指定的K对应的value,拿着这两个值呢,看数据库里边校验一下这个名的这个密码对不对,但是也有可能用户这块呢,他就没有写忘了写了,然后点开下登录,这个相当于这个值呢,是不是就闹啊,哎,那你如果试图给他往这个map里边放的时候呢,这个你要往哈table放,它不就控制人异常了,哎,这个见证性呢,就稍微差一些啊,所以呢,我们主张呢用哈希map。啊,去做一个替换啊,那和我们前边这个A一样,即使后边咱们涉及到了多线程问题,咱们呢也不会因为它是安全的而用它,而是我们用collections加S类工具类,咱们这章最后去讲的啊,里边有这个相关的方法,我们把它变成一个安全的啊,也不用它了,这呢就关于这两个呢,做了一个对比啊,这个是先先说先说清楚它俩,然后呢,我们再回过来看,这个叫link的哈奇map跟我们set,呃哈set和link哈set一样啊,它是它的一个子类,在原有的这个map的基础之上加了一对指针,其实是吧,就是我们就形成这个链表结构了啊,那形成它的特点呢,就是能够保证,诶这个写叫保证啊,保证呢,在这个便利啊,这个脉回元素时。
10:38
哎,它呢是按照哎可以按照咱们添加的这个顺序,哎,实现这个便利啊,那么这个原因是什么呢?啊原因呢,我们就是在这个原有的啊原有的这个哈希啊map这个底层结构基础上基础上,然后呢,这个呃添加了呃一对呃叫叫叫叫什么呀,叫引用吧啊或者叫一对这个指针啊然后呢,这个呃表明呃天表明或者叫指向吧,指向这个呃前一个和后一个元素,哎就相当于我们记录了一下啊,我们当前添加的这一对啊这个k value这一对,它的前一个是谁,它的后一个是谁啊我就有这样的一个记录了,那使得呢,我们电力的时候呢,就能按照这个。
11:38
顺序去实现啊,就是我们找元找它的前一个和后一个呢,就更加的方便了啊,那基于这样的这个点的话呢,我们什么时候会去用它呢?哎,我们说对于这个频繁的啊,便利操作哎。这个此类就是我们当前的link哈希map,它的执行效率。
12:00
啊,要高于咱们的哈希map,那相当于就说清楚了,大家什么时候你去new link的哈希map,就是你翻来覆去刚添加俩啊,可能要变历一下啊,又添几个又要变历是吧,频繁的去变历,那你可以考虑用哈希map,呃,Link哈希map。那除此之外呢,没有额外的一些需求,你就用哈map就完了,好这是它,然后在下边呢,叫tree map tree map呢,类似于我们说的这个tree map,那我们可以保证啊,可以按照添加的啊,添加的这个KY6啊,这叫建值对了啊,进行排序啊,然后呢,实现这个排序便利。嗯,就是我们添加进的这个数据呢,它也是像吹set一样是有序的,那么吹set当中咱们填的是一个一个的元素,那就填你这一个元素,看看这些元素谁先谁后了,那这里边儿我们涉及到K,涉及到value,那它排是拿谁排呢?
13:04
对,这块我们要指明一下,它是按照这个K来排的。啊,按照这个K来排的,比如说你这个K这常叫刘德华,这个呢叫张学友啊,然后这个VALUE6呢,这是他多大了,这个VALUE6呢是他多大了啊,我们是按照他们俩,比如说这个刘德华张友,你想按照这个姓名先后顺序排,那就按照姓名排,跟这个没关系,这个VALUE6呢,不会拿他去排的,只会拿我们这个K去排,保证按照它的顺序镜排序,实现实现排序便利,那么此时啊是使用这个K啊这个或者这样说吧,此时呢,这个考虑啊,这个key的这个自然排序啊,或者呢,定制排序。哎,这就可以了啊,那这个tree map的话呢,咱们其实用的呢也比较有限,还是这个重心呢,在我们这个自然排序和定时排序,而这个内容呢,咱们也都讲过了,所以说到这个tree map的话呢,我们只是这个关心一下,测试一下就可以了,那它呢,相较于咱们其他的这个像哈希map,另哈希map哈希table来讲,它的底层结构啊不太一样啊,这儿呢,我们这个相当于格外的说一下,就是它呢是有排序这个特点呢,它的底层哎使用的呢是哎红黑树。
14:24
红黑树呢,属于树的一种啊,再往下分就是二叉树的一种,再往下分呢,是排序二叉树中的一种特殊的一种树形结构,这个呢,咱们不用关心太多,这里边这个点还挺多的啊,红黑树这一块啊,大家呢,如果有兴趣呢,你可以专门呢看一看呃,相关的一些帖子来关于它的一个说明,这呢我之前讲哈希呃,这个吹set的时候呢,说过这个事儿啊,有一个帖子呢,写的还可以,大家呢,你可以看一下这个帖子啊,写的呢,关于这个红黑树的一个理解啊,那对于大部分同学来讲呢,就是可以就不用看了啊,那这块呢,它红黑树呢,还是相对来讲属于复杂的一种树。
15:04
啊,你只需要知道。啊,只需要知道tree set tree map底层用的是红黑树啊就行了,那它是用的树形结构,那我们其他的呢,那哈希map典型的就是哈希map和哈希table了啊,这不除了他就说的是这俩嘛,这两个呢,他们的底层。啊,底层用的是什么呢?哎,这呢,你要说的准确一点,还得考虑到JDK的版本的问题。啊,这一些版本问题,那呃,我们这块呢,就诶在这呢,可以简单先写一下啊,就是我们的哈希map,诶它的这个底层。啊,这个底层底层呢,呃,最初的时候呢,就是数组加列表啊,但是这种呢,是仅限于我们JDK这个七啊及之前这个版本当中,然后呢,在这个JDK8当中呢,给他做了一些优化,提到了叫数组加链表啊,再加上红黑数,这呢是我们JDK8的这个版本,那么为什么要给它再加上这个红黑数啊,主要呢,也是为了提升它的一个呃效率,那怎么叫提升效率呢?这个我们讲一下这个底层结构大家就知道了啊呃,我们先不具的不具体的去展开来说。
16:23
好,这是关于它的这个底层结构的一个事儿,那么还有一个呢类叫properties。这个properties呢,从这个名字上来看呢,好像不太像是一个map了。但是呢,你要注意它还是我们这个map这个体系下的啊,它的这个特点呢,我们说常用来啊处理啊,这个叫啊配置文件,哎,常用来处理这个配置文件这个情况啊,那它的这个特点呢,就是首先作为我们哈奇table的一个具体的子类,这是其一,其二的话呢,就是它的这个key啊和value。
17:02
我们说啊都是string类型,哎,这呢就是它的一个特点,那么咱们说到这个properties的时候呢,到时候我们举个例子,哎,让大家呢简单去体会一下它来处理配置文件的这个事情啊就OK了,这呢是咱们关于这个map它的一些实现类的一些特点,这块呢大家首先呢得清楚啊,那这呢涉及到两个典型的面试题,第一道面试题那就提到了,也是极其高频的,需要大家呢都要掌握的,就是哈奇map的这个底层实现原理,需要我们来看它的这个源码,其实这块呢,只是泛泛的说了一下。啊,那就涉及到呢,底层的这样的一些结构,这是第一个典型的面试题,第二个的话呢,这个频率出现呢,就要稍微低一些,大家呢关注一下啊,出现频率低一些,也是比较老的一个免试题,那就是问哈希map呢和叫哈希table啊,他们的这个啊一种。
18:02
那这个异同的话呢,咱们在上边其实都写到了,这是一个点啊,这是一个点,哎把这个事儿呢,去描述一下就行啊,去描述一下就行啊,那实际上的话呢,呃,我们还有一个类就不想在这儿去讲了,以后呢,咱们讲这个Java的一些高级知识的时候呢,再说啊谁呢还提到了一个呢,叫current啊哈希map,那可能会被问说current哈希map呢,它与咱们的这个哈希table的一个区别。哎,或者叫这个一同吧,诶这个问题呢,咱们暂时呢就不讲了,主要原因呢,就是咱们不想再给大家去引入这个car韩信ma了。诶这个是什么结构呢?就是涉及到咱们这个用多线程去访问map的时候,咱们说过了,说这个呢是线程不安全的,这个呢是线程安全的,那似乎呢,咱们是不是就应该选它呀,啊选它就让哎用它线程安全,或者即使你不用它,你用的哈奇map,你把它变成安全的,但是这时候呢,还会有个问题,就是说我这有好多的线程。
19:12
好多线程我现在都要访问这个map了,不管你是用它也也好,还是说你把它变成安全以后去考虑,总之呢,在这个同步的代码块或者同步方法之内,它是一个单线程的问题,这个咱们前面是不是说过这个事儿啊,诶说过这个事儿就是这样的话呢,其实是导致我们这个多线程操作这个共享数据的时候呢,效率偏差。那为了呢,在高并发的这个场景下,我们操作这个map的时候呢,让它的执行效率更高啊,执行效率更高这块引入了一个新的结构叫current哈希map。啊,使用了一个它这个呢,它能实现那个呢,叫分段锁的一个技术,就是说我们呢,去操作这个数据,你现在不是好几个线程吗?呃,原来的话呢,我们说在这里边呢,就让一个操作其他的等着,呃,现在不这样了,现在呢,我们把这个数据呢,可以分成好几块分段锁就是分好几块,然后这块呢,现在你访问这块呢,这个线场你访问这块。
20:05
啊,就是让他们可以相当于呢,能够体现出来同一个时间段之内呢,似乎有多个线程都在操作这一些共享数据了。就像你买票一样啊,这个咱们全国就这一趟车啊,比如说几点到几点的,全国呢叫T1这趟车,这趟车呢,你在好多点都去卖票,那有的这个点呢,我们就只卖这一段的票,这123这个车厢的,那有的呢就卖456这个车厢的啊这样没必要呢,说整个这个车里边呢,我们全锁住,就让一个先生去在这儿操作一下。哎,是这样啊,这个咱们后续啊会提到,哎,这样的这个结构啊,好在这儿呢,我们就不多说这个事儿了,那这两个问题当中呢,这个问题咱们上边已经解决了,那么后边呢,咱们重点呢,说的就是哈希map的底层实验原理。啊。
我来说两句