00:00
好,那么在执行引擎这一章呢,结束以后啊,诶咱们呢,按正常来说呢,其实下边就可以来讲这个叫垃圾回收了啊,那这块呢,我们又给大家补充了一个章节,叫做string table,就专门呢我们来讲一讲关于string的一个使用这个string的话呢,不管是大家面试这个叫中级成员还是叫高级成员,这个的话呢,都是大家逃不了的,并且的话呢,String在咱们实际开发当中也确实啊用的非常的广泛,对吧?诶这个大家应该都很清楚啊,那么在面试当中啊,关于这个呢,涉及到的点呢,一方面就是针对于它底层的这个内存结构是吧?诶涉及到相应的一些问题,那另外一方面呢,就是关于这个string的相关的一些算法啊,在这个笔试当中啊,经常呢,也会去考这个死string相关的,包括呢,我们所谓的这种排序啊,涉及到数组相关的一些问题呢,都会出,OK,这是这样子的,那么咱们通过这个GM这个角度啊,把这个string呢再来提一提啊,因为呢,咱们讲了这个底层的内存结构以后,我们再来看这个string呢,咱们就可以说呢更加透彻一些,现在呢也是对大家呃。
01:00
开发当中经常用这个词,String呢,我们有一个更深入的一个剖析好,那么这一章里边有一些内容啊,大家呢,应该都是熟悉的,或者呢,针对不同的人来讲呢,它这个熟悉的程度呢,也不一样,那有的人呢,可能关于string呢,只会用,从来呢,没有考论过或者考虑过说它底层的一些特点啊,就是正常用啊,也没有考虑过多的说这个性能的问题,是吧,那么这一章呢,我们就把这些关于性能,包括我们不同string的这个对象的一个,呃,创建方式。来给大家讲一讲不同的写法,它其实底层的一个结构的这个不同,包括性能的不同啊行,嗯这呢是我们这一章呢,主要的几个点啊,首先呢,提一提关于string的这个基本特性,然后呢,是这个string的一个内存的分配结构啊下边呢,就涉及到我们通过几个练习呢,来说一说这个string的常用的一些操作问题,诶重点的话呢,就是我们在开发当中经常呢,大家遇到这个操作呢,一个呢叫做字串的一个拼接操作,哎,我们使用这个叫连接符来实现的,对吧?那么这个连接符它对应的我们这个底层呢,是怎么样来进行一个处理的呢?呃,这个呢,我们要讲一讲啊,另外呢,就是非常重要的一个方法呢,叫做in inter方法啊,当我们调用int方法的时候呢,我们就会从这个字符串常量池当中去生成一个对应的字符串常量,对吧?哎,那很多时候呢,我们使用正确的使用这个in的方法呢,是可以提升我们程序的一个执行效率的。
02:16
诶,这个是大家注意的啊,然后我们专门的来讲一讲这个in inter,然后另外呢,关于这个string table啊,就是我们这个字串常量池呢,它的一个垃圾回收问题啊,以及呢,我们后边呢提到这个,呃,后边呢,咱们再讲呢,就是关专门讲这个JC了啊,这个其中我们现在呢,默认的JDK8中使用的呢,叫j first的这个垃圾回收器,那这个J当中呢,提到了一个叫关于string的一个出驱虫操作啊,那这呢,我们也给大家呢提一下,这呢就整个我们关于string呢,想给大家解释的这样的几个点,好那我们就按照这个顺序呢,一个一个来进行说进行说明,那第一个呢,也是大家相对来说是最熟悉的啊,叫做string的基本特性。来,我们看一下。啊,String的基本特性这块我们一块过一过啊string的话呢,我们称为呢叫字步串,那它呢是用一对双引号呢引起来来表示,那这里边呢,其实一说到这个问题啊,我们又可以引申出来,这个string的话呢,咱们呃从大面上来说,它的创建方式啊,毕竟人家是一个类嘛,是吧,这个类的一个实例化方式啊,实际上是有两种方式的啊,一种方式呢,就是咱们直接呢,呃就是呃,我就直接写在这儿了啊S1右边呢,直接就是一个双引号。
03:21
诶,这个我们用是英文格式下的啊,这一个双引号,双引号里边,比如我们写一个叫爱的硅谷,OK,这呢就是我们称称把这种啊称为叫做字面量的一种定义方式。OK对吧,哎,那除了这个之外呢,另外呢,毕竟呢,人家还是一个对象嘛,是一个类嘛,所以我们呢,还有这种叫new的方式,那在new的这个string里边呢,我们放一个哎,又是一个字符串了,其实哎,这里边咱们也放具体的信息啊,比如来一个hello。行就这样子的啊,从整体上来讲呢,这个string呢,我们说有两种这个实例化的方式,呃,那么这种呢,就是来看这个string呢,更像是一个类啊,因为你通过new的方式呢来实例化的,那么这样的方式呢,从形式上来看呢,我们说更像是一个基本数据类型。
04:06
对吧,因为只有基本数据类型呢,我们才会比如int一个I啊,直接呢符合值啊,这个词string呢,相对来说它比较特别一些,很多人呢,潜意识当中会把这个词string呢,误认为是一个基本数据类型,或者呢是贴近于基本数据类型的一个结构,就是因为呢,它在实例化的形式上来讲啊,确实还是跟基本数据类型呢比较像的啊。OK啊,这个呢,大家先有一个理解啊,非常简单一个事儿,然后另外呢,我们提到说这个string啊,它声明的是一个final,它呢是不可被继承的,包括实验这个接口啊,这块呢,咱们就直接呢,通过这个代码呢来看一下。好,这个呢,我就随便的,其实在一块直接呢,Ctrl shift t也可以是吧,诶在这呢,咱就找这个叫。那找这个叫string string的话呢,记住直接点开就行啊。哦,这是我们前面演示这个,呃,叫双星委派机制的时候呢,自定义的这样一个词缀啊,咱不想看它啊,Ctrl shift t,我还是string找的是咱们所有的这个程序当中的。
05:00
啊扎2.la包下1.8里边的是吧?行过来了,这呢就看到我们这个string,它呢声明称是个final,也就说我们这个类啊,它不可以被继承,那咱们也没有呃造过这个string的子类是吧?哎,它刻画磁串方面呢已经是非常完备了,没有必要呢去提供它的子类,那其次的话呢,我们说它实现了叫sable这样个接口和comparable这个接口,包括呢,插sequence啊这个磁符序列的接口,那这呢主要体现在就是我们在跨进程进行数据传输的时候,如果这个数据呢是以string的方式进行传输,那天然的话呢是没有问题的,因为已经实现了这个序列化机制。哎,跨进程之间的一个传输数据是吧,包括呢,我们使用这个杰森,杰森本身本质上来讲呢,它也是一个字符串嘛,诶因为呢,诶我们实现序列化了,所以呢,就可以跨进程了,去传递这个string啊,那另外呢,就是有一个叫comparable,那表示呢,我们当年这个string的任何实例呢,它都是可以排序的。那也可以比较大小的啊,这个呢,我们用的场景呢,也实在是太多了,像大家这个联系人啊,联系人的话呢,诶自然的我们并不是说你有新把一个朋友呢,添加到你这个联系人列表里了,它出现在这个最后一个位置,不是的,而是呢,按照他这个拼音的方式呢,是不是放到他该有的那个啊,Abcd的一个顺序放在那儿是吧?诶这个主要原因呢,是因为我们找到比如说你对应的这个汉字啊,它的这个拼音啊,这个拼音的话呢,本身是可以排序的,那排序的一个前提呢,就是可以比较大小。
06:21
啊,这呢,对于大家来讲应该都是非常简单的问题哈,咱就不多介绍了,然后呢,接下来我们看到这个,呃,提到这个问题,就是这个string啊,它在底层存储数据的时候呢,咱们用的这个结构,那JDK1.8的时候,其实我刚才这块看的就是JDK1.8,可能大家没有注意啊,我再重来一下ctrl shift t啊,这个时候我们找所有的这个places,咱们看的是这个,你看1.82T点文件里边对吧?哎,我点击一下进来的,在GD1.8的时候呢,我们底层呢,用的是差异型数组。哎,或者有的同学呢,可能呃,没有具体去关注过我们GK8之后的各个版本的新特性啊,可能呢,把这个认为呢,是所有的版本中都是这样子的,其实不然啊,我们说字符串字符串,这就是个串。
07:04
其实它就相当于是个象形文字是吧?呃,当然呢,夏天的时候呢,呃,在这个不管你是一线城市二线城市还是哪哪哪是吧,咱们都能看到这样一个呃符号,在夜晚的这个这个什么月光下啊飘来飘去,然后呢,这个呃灯光下呢,都会有那么几个人在那坐着啊,一股烟啊,在烤羊肉串呢,是吧?哎,羊肉串也是这个串,那羊肉串呢,这个位置呢,放的都是一块羊肉。那字符串的话呢,这一个就是一个串呗,字符串字符串对吧,那我们很好理解呢,就是字符串呢,它底层呢,诶或者说我们真正存储的这个数据啊,用的是一个差询数组啊,这个呢,应该算是非常好理解的啊,当然这种事情呢,我们说终结到了JDK1.8,那在JDK1.9的时候呢,就不是这样的一个行为了啊这个1.9啊,这呢是我们这个第13章当中啊,我呢随便打开了一个这个代码,那此时呢,我要是按住这个CTRL键呢,我去点击的时候,你看默认的这个时候是不是还是这个1.8呀,点一下看就跑这了是吧,那如果看JDK1.9中的这个代码,可以这样子,我们点这个结构。
08:06
结构呢,这是我们第13章对吧,然后大家在这个位置呢,去选择,那在这个位置dependence啊选择的话呢,找一下这个1.9。啊,选择1.9这个,你把1.9这个GDK呢,可以提前的安装一下啊好,这个应用一下OK。可以了是吧,那此时的话呢,我们再去点那个轮。诶注意这时候的话呢,我们看到的实际上就是这个1.9当中的啊,你看我这在这儿呢,实际上已经导入来这个1.9了啊,那在这种情况下呢,大家会发现我们底层存储这个死string中的数据啊,咱们用的不再是叫差型数组容器了,而是呢叫BAT数组容器,你看这里边清清楚楚的写明这个结构了,还是叫Y6,当然呢,这个类型呢,已经完全变了。啊,已经发性变是吧,哎,这个呢,是非常重大的一个改变啊,那这个改变的话呢,也在咱们这个GDK9的对应的这个GDP啊254这个里边呢,写的非常的清楚,大家呢,如果你要是想看这个官方的这个解释的话呢,直接呢把这个哎粘过来啊回车一下。
09:08
啊,这就进来了,诶,关于我们这个string的它的一个整理啊,或者叫一个压缩啊行,然后呢,下边呢,就写的比较清楚说啊motivation就是我们这个动机是什么,咱们为什么呢,要把这个string底层这个结构呢做一个修改,包括呢它的一个具体的描述。啊,这呢都写了是吧,那我就不在这看了,咱们把这个内容呢,我就直接粘出来呢,放到这个PPT里边了,咱们在PPT里边呢,带着大家一块来读一下。哎,这里边写的非常清楚啊,我们为什么要做修改说呢,当前的具体这个关于string这个类的实现,哎,它呢是存储在我们说叫呃character就是字符当中啊,使用的是一个叫查询数组。啊,那这个差音数组呢,咱们知道它里边是一个差呢,占两个字节嘛,啊相当于是16个bit嘛,对于每一个字符来讲,那数据呢,存储在不同的应用,存储在不同应用中的这个数据,我们在做一个集合的时候呢,还发现说呢,这个string啊,它是咱们这个堆空间当中存储数据的一个主要的一个组成部分。
10:10
啊,就是刚才呢,是我们先说清楚了,是一个现状是吧,然后接下来呢,是通过这个实际的,呃,数据呢,分析呢发现这个,呃,String呢是咱们这空间中的一个主要部分,哎,同时的话呢,诶什么情况啊,这是一个关键。大部分的这个string的对象发现呢,他们包含的都是一些拉丁文,或者叫拉一些拉丁字符,那么对于这个拉丁字符来讲的话呢,这里边咱们呃想一想啊,一个是那个二码会代表的是吧?还有一个呢,咱们涉及到一个字符集呢,叫ISO8859杠幺,这个ISO8859杠幺啊,它是欧洲码,欧洲码呢,它们其实用256啊,它256啊其实也是一个BAT码就能存下啊,对于这个阿克码的话呢,其实128就能存下是吧?啊,小写的A到Z,大写的A到Z啊,零到九,再加上一些这个常用的标点啊,其实128就够,总之的话呢,就是不管你是ISO889杠幺也好,拉丁也好,还是美国用的这个这个也好,他们呢,是不是一个字节就都能存的下。
11:05
对吧,哎,一个字节都就能存得下,当然了,对于咱们说汉字来讲,一个字节肯定撑不下啊,你比如说256个字了,你再给我补个零二两千五百六十个也不够是吧?啊,对于人家这个拼音文字的这些国家来讲呢,人家用不了那么大啊,所以这里边发现咱们这个大部分在堆空间中的这个string对象呢,它只是一些拉丁的一些字符。啊,你要是这样的话呢,像这些字符,它实际上呢,用一个BAT呢,就能够存储,那就导致呢,咱们实际上会有一半的这个空间是不是被浪费了,就unused是吧?哎,这就是目前的一个现状,那基于这样的现状呢,咱们就做了一个修改说啊我们可以做一个change,把这个内部的一个呃结构呢做一个取代。从一个UTF-16就相当于你是两个字节嘛,这样的一个差型结构呢,咱们改成一个BAT型的数组,但是你改成BA数组吧,也不行,你像咱们汉字啊,你一个中文的中,那在内存当中,我们就应该是用两个BAT来存的。
12:04
毫无疑问对吧,那怎么办啊,那这时候呢,就是像这个abcd啊,人家改成一个BAT了,你像这个中文的中啊,你还是用俩BAT,那这是怎么办啊,咱们除了呢,把它改成是一个bad数组之外啊,再给它补一个啊,就是我们这个字符编码及的这样一个标识。哎,这样个标识,也就是说呢,如果你是ISO8859杠幺或者拉丁呢,那你就用一个BAT去存,如果呢,你要是像其他的这些,哎字符集的话呢,你还是用这个两个字节呢去存。那这呢就非常好是吧?哎,写的非常清楚啊,好,那么既然我们这个string做修改了,哎做了修改以后呢,那么像string buffer string builder啊,以及其他的一些凡是呢,在不同的位置使用字符串的场景,有没有做修改啊,诶这里边写的非常清楚,说基于string的这一类,比如说呢,像abstract stream builder啊,Stream build和stream buffer,包括呢,我们house虚拟机内部的一些固有的啊,一些string结构呢,也同样的做了一些修改。
13:01
啊,这呢写的非常清楚,好,那当然呢把这个事明列出来,那不管呢,你是面试这个中级还是高级,在必要的谈到这个string的时候呢,要把这个事呢给他指出来。啊,要把这个事指出来啊,当然对于我们开发人员来讲呢,实际上你感受不到呢,说这个点改完以后呢,对我们的一个直接影响是什么?因为我们既不是语法层面的修改,也不是API层面的一些扩充或者是删除,所以对于你来讲啊,你似乎感觉是没有什么变化的是吧?当然底层呢,诶却实实在在的做了一个调整啊这个大家清楚啊,行,然后在下边呢这块提到说这个string啊,它呢代表叫不可变的字符序列。哎,这个大家关于string呢,一定要去强调这个问题啊,叫做不可变的字符序列,简称呢叫不可变形。哎,这个你别断句错了啊,不可变的一个特性是吧,你别整成不可变性了啊。它还没性别是吧,哎,不可变的一个特性啊,行,那么这里边所谓的不可变的这种特性是什么意思啊,我呢从三个角度呢,做了一个诠释,这三个角度呢,对应的我又写了三个代码,那咱们呢,就直接来看这三个代码,哎,通过这三个代码呢,咱们想强调的啊,就是来体现这个诶string的不可变形。
14:12
不可变性是吧?行,那么这呢,我们就一个个来看啊呃,大家呢,首先应该有一个常识,就是我们通过这种自面量定义的方式,哎自变量哎定义的这个方式,那么我们这个时候的这个ABC它呢,是不是在呃存储在我们字符串常量池里面对吧。哎,尝尝吃当中OK行,这个呢是比较清楚的。英问的啊,行,那么字符串常量池呢,一会儿咱们也会强调字符串常量池当中是绝对不允许放相同的字符串的,也就是说我们这有ABC,我这呢再来一个ABC啊,我先暂时呢把这个先注释一下,那么这两个ABC我们实际上共用的是字符串常量池里边的统一个对吧?那这呢是占咱们这边方法内的嘛,哎,局变量是吧?哎,它就放在这个局部变量表里边,这两个呢,是占空间中的一个S1啊,一个呢叫做S2,我就简写了,实际上呢,这用的是局部变量表,然后呢,这是我们堆空间,堆空间里边呢有叫组上插向池,那这里边有个ABC啊,咱们在JDK7以后呢,不都放在堆空间里了吗?
15:20
哎,那么这呢就指向它了,然后S2的话呢,也指向它,哎,那这时候我们如果去判断它俩这呢,注意是判断地址是吧?哎,判断地址呢是否相等,那很显然呢,它俩呢就是一样的,所以这个呢就是个处啊,那对应的他们打印的结果呢,那就是ABC。哎,这个呢,对于大多数人,绝大部分同学来讲,这都是非常简单的问题是吧,就是问这个问题呢,是不是感觉有点侮辱你智商啊,然后呢,诶,当我们把这个SE呢改成叫hello的时候,我们这时候呢,想要讨论的就是它会在原有的ABC基础之上啊,把这个堆空间中,你这不是叫ABC吗?是把这个ABC呢直接给它干掉改成hello吗?
16:00
哎,这要注意不是的,那就是你再重新造一个角哈,是吧?哎,那么并没有影响我们原有的S2这个值,哎有此时呢,你再去判断说它俩呢,是不是相等啊,那显然呢,是不是他们已经指向了不同的这个数据了,是不是就变成个false了。哎,很清楚是吧,哎,这个是第一种情况。嗯,就这样子是吧,行,那么这S2呢,本身人家是不变的啊,所以它呢还是个ABC,这呢是我们重点要强调的点,S1呢哈,行,然后看第二个情况,哎,我们这S1S2还是它,然后呢,在S2的基础之上啊,我们直接呢给它再拼接一个字符串叫DEF。啊,直接拼接堆空间当中,这样我就不画了啊,这里边儿有一个叫ABC啊,足链长岭池里边说呢,我们现在S2呢,S1S2呢都指向它,现在这个S2呢,就补了一个叫DF,能在现有的ABC后边呢去补DF吗?哎,这要注意,不管呢,你是差型数组还是说BY数组,那数组的话呢,当我们一旦你定义好这个字符串以后呢,其实底层这个数组的长度呢,也就定死了,你在后边呢,试图去补一个,呃,这个这个我们说叫DEF,那数组本身扩容呢,我们说也不能往后补啊,你是不是得重新造一个呀。
17:12
对吧,这是其一是吧,那其二的话呢,就是我们本身的这个字符串场景池里边,只要你做修改都得去重新创建。哎,这才体现叫不可变的特性嘛,就是我这个呢,就存到这儿就定死了,你不能改啊,你要改你重新造一个,这就我们所谓的叫不可变性,哎,只要把握住这个大原则呢,大家一定就做不错了啊,那既然呢,你这样去处理,那S2的话呢,毫无疑问你做修改了,那你肯定是改成这样的,但是这个S1的话呢,还是ABC吗?加上双赢,加上这个注释是吧,还是BC。哎,就是你并没有对S1呢做任何的调整。嗯,就是这样一个场景,行,那也就是说呢,对于呃,就是特别小白的这个成序员来讲呢,就是呃即使你不知道说S1S2呢,共应的是一个,你就这块看是吧,S2呢,你改了,那S1怎么会改呢,不会改是吧?哎就蒙呢,可能完全什么也不懂,可能也能蒙对啊叫无知者无畏,反而对了,对吧?哎,就跟我有时候玩一些游戏一样,或者玩一些牌,就是你懂得特别多的时候呢,反而呢,呃最后还容易输啊,显得呢,就是那些刚会的人呢,咱们经常叫什么傻瓜抓大牌是吧?哎,他呢,就通过一些最简单的一些规则啊,他觉得能做出来。
18:24
那有的时候你懂得多的时候,反而呢,倒容易这个限制你的一个,呃,这个操作方式是吧,当然了,咱们肯定还是得你不能知道第一个层面哈,这个不知道,他俩底层一开始共同的同一个,那那显然不行,咱们呢,要达到是一个更高级的一个层次,就你不能是最初的你经历过一次否定之后呢,再来一次否定啊,否定之否定这个时候呢,你的整个呢,理解认知啊才提升大家呢要达到这样一个层次啊,诶非常喜欢一个词呢,叫做认知,诶大家呢,诶不管你是学编程也好,你还是这个从事其他的这个行业也好,生活中也好,其实我们不断的生活当中,就是要提高大家的一个认知能力。
19:00
啊,这个呢是非常重要的啊,认人能力呢,其实也决定了你的一个生存能力啊,我记得之前呢,看一个例子,就说一个一个富人是吧,亿万富翁,然后呢,他把自己这个给了好像是三个月的时间吧。美国的一档节目哈,然后呢,他就身无分文的,呃,去到一个陌生的城市,他就看通过三个月的时间,他能不能把自己打造成一个,呃,这个身价过百万的是过百万的,我记得是啊,三个月的时间,呃,那他呢,最后呢,还接近于这个目标了,基本上是接近于这个目标了哈,呃,应该说很厉害了,那身无分文他怎么能达到这一点呢?其实还是呢,他的这个认知能力啊,生存能力,这个生前能力是吧?哎,是比较强的。就是大家呢,其实也应该是这样子的哈,还有以前咱们看过一个例子啊,说这个呃,放羊的一个孩子是吧,你放羊的目的是什么呀?放羊目的呢,是以后长大娶媳妇生孩子啊,生孩子的目的什么,接着放羊,那我们会嘲笑人家。啊,你可能是从你的角度来讲呢,你是觉得他的认知能力是有限的,但你从他的角度来讲一点问题没有是吧,那也有可能我们现在呢,认为的一些观点呢,在呃,所谓的一些上层人来看呢,是我们呢,又相当于是这个放放羊的这个孩子一样,哎,其实就是这种是吧。
20:10
好,那么这是我们说的第二种场景啊,然后第三种场景呢,是这样子的,我呢也不是说再重新指向一个字符串,也不是呢,在后边呢,试图去呃再拼接一下,而是呢,我在你现有这个字符上基础上呢,能不能做一个修改呢?比如我这呢是一个ABC。啊,我这是个ABC,然后呢,我把现有的这个字符串当中的某一个A啊,改成一个,诶这样行不行啊。想这样做是吧?对,空间里边还是ABC,能把这个A就直接改成M吗?如果要是能的话。如果要是能的话,那这里边儿S1S2呢,是不是就都变成了叫mbc了。哎,我说的是,如果要是能的话是吧,哎,那事实上呢,不是跑一下。事实上的话呢,我们发现这个一呢,是不是仍然是叫ABC啊。因为你这里边呃,做了一个replace之后呢,返回的呢,其实是你改以后的,而S1本身没有变,这呢其实也体现了我们所谓的叫不变性嘛,就是返回的这个数据是应改以后的啊,本身它呢没有变啊,总之的话呢,就是它这三个方面啊,都体现了我们说的磁锥的这个特性啊,叫做不可变性,这个大家呢一定要掌握住啊行,那下边呢,提到这个点说呢,通过自变量的这个方式啊,给一个字符串赋值啊,此时的字符串值呢,生命在这个常量值当中啊,这个咱们刚才在这呢已经说到这点了,行,这呢属于一个特别基本的一个问题啊,然后大家呢,可以把它呢掌握住。
我来说两句