大家好,今天我们来学习 java 中的 arraylist。 首先要记住 arraylist 是 一个动态数据库,实现了 list 的 接口,可以存储各种对象,而且大小能自动调整。比如它比普通数据库灵活多了,适合存储不确定数量的元素。 接下来我们看如何声明和初识化。 alexis 语法是 alexis 类型特列里斯等于 l alexis, 比如 l alexis t string names 等于 l alexis。 这样就创建了一个字母串列表。大家要注意案情,制定了存储类型,避免类型错误。添加元素很简单,用 a d 方法,比如 list dd。 java 就 把元素加到末尾了。 a, d, d 还支持在指定位置插入,如 list a d d first, 插入到开头,要记住这是动态添加,列表会自动扩容。访问元素时用 get index 方法缩隐,从零开始,比如 list get 零,返回第一个元素,大家要注意缩隐范围,如果越界会抛出 index auto off bounds exception。 异常 编程时要小心。删除元素有两种方式, remove int index。 删除指定位置的元素,如 list removes 零或者 remove object o。 删除第一个匹配的元素,如 list removes。 java 删除后,列表会自动调整大小。检查列表大小,用 size 方法返回元素个数 s m t, 检查是否为空。比如 if list s m t s m t 才可以判断列表是否没元素, 这在处理用户输入或数据时很实用便利。 alexed 可以 用 for 循环 for in i 等于零 i list size size 加加 for 或者增强 for 循环 for string i list 兹德还可以用 iterate 迭代器。 便利时要注意不要修改列表结构,否则可能出错。 a realist 和普通数组的区别,数组大小固定声明时指定 a realist 大 小可变,自动扩容,比如 int r r 等于 new int 十大小不能变, a realist 能随意添加元素, 大家要理解这个核心优势。县城安全方面, our list 不是 县城安全的,如果多县城同时修改,可能导致数据不一致。要记住,在病发环境下,可以用 collections sincronized list 的 包装或改用 copyright list。 性能注意点, aureolelist 在 末尾添加元素很快, o 一 但在中间或开头添加删除较慢。 o 一 因为需要移动元素,比如频繁在开头操作时考虑用 linkedlist, 大家要合理选择集合类。
粉丝325获赞2165

大家好,今天我们来学习 java 中的 list。 list 是 集合框架中的一个接口,代表有序的元素集合。简单说,它就像一个有顺序的盒子, 我们可以按锁银访问元素,比如第一个,第二个。要记住,这是 java 处理集合数据的基础哦。要创建一个 list, 我 们通常用实线类,如 arraylist, 或者 list, 等于 new arraylist 的 s, 比如这样就能创建一个存储字串的列表。大家注意,范型歹离指定元素类型,确保类型安全。添加元素时用 add 方法,比如 list add 叉哇,就把叉哇加到末尾。 add 意思还可以指定位置,如 list add 零 first 插入到开头,要记住,如果缩引超出范围会报错, 别犯这个错误哦。获取元素很简单,用 get 方法传入缩隐,缩隐从零开始,例如 string first 等于 list get 零获取第一个元素。大家要注意缩隐不能超过 size 负一, 否则会抛出 index auto of bound section。 异常删除元素用 removes 有 两种方式, remove 用的 index 删除指定所引的元素或 remove object 误删除匹配对象,比如 list removes 零删除第一个元素, 记住删除后元素会迁移,所以会变哦。便利, list 是 常用操作,可以用 for 循环 for int 等于零 i list size size i 加加猜测,或者用 for reach for string s list strike 更高效的是迭代起 iterate, 避免病发修改问题。 想知道列表有多少元素,用 size 方法,比如 int count 等于 list sizes, 返回当前元素数量, 这是个 o e, 操作非常快。大家要记住在循环中用它来避免重复计算。 arraylist 是 基于动态数据库实现的,所以 geti 随机访问很快,是常数时间,但插入或删除元素时可能需要移动数据,效率较低。 比如在中间插入元素时, arraylist 不 如 linklist 快。 linklist 是 基于双向链表的,插入和删除元素很快,因为只需调整指针。但 getty 随机访问慢,需要从链表头便利,比如频繁增删场景,用 linklist 更合适哦。 最后要注意, arduino list 和 link 的 list 都不是县城安全的,如果在多县城中使用,需加锁同步或改用 copy on rt arduino list, 比如多个县城同时修改列表,会导致数据不一致,大家要避免这个坑。

今天开始呢,我们来学习核心内库中一些比较有用的类。这节课呢,我们来讲一个叫 i release 啊, 那之前呢,我们如果想存储多个值,或者是多个对象,用的是什么?是不是数组啊?但是数组呢,它有一个最大的问题, 数组的容量是固定的啊,比如说下面这个例子,我这是一个字不串数组,里面是不是放了五个字不串元素? 但是这个字不串数组啊,它的容量在一开始就固定死了,比如说现在它就容量固定成了五,如果你想再多放一个元素,行不行啊?就不行了啊,就放不下了,那这个怎么办呢?怎么办? 哎,我们得再创建一个比原来这个数组大一点的一个新数组,然后把旧数组的元素还得一个一个迁移过去,比如说旧数组大小是不是五啊?那我们再创建一个新的数组啊, 这个新数组我们叫个二瑞一,你有一个 spin, 对吧?新数组的大小是不是比原来得大一点,比如说我设成六。好,这样呢,这个新数组创建好了,然后新数组里是不是还没内容啊?我们可以打印出来看一下啊, 当然打印数组呢,你可以去便利,对吧? array 零 for i, 这是以前教过的一个快捷键。 好,然后我们可以打印 re 零括号 i, 但是如果仅仅是为了打印,你写一个循环好像有点, 这个杀鸡用了牛刀是吧?哎,确实能打印出来,这里再给大家教一个啊,比较好的查看数组数组内元素的内办法啊, 我们可以这样做,用一个工具类叫做 arrays 啊,从它的名字大家都能看出来, array 就是数组的意思啊, arrays 就是跟数组相关的一些工具方法啊,在这个类里,我们可以用它的一个叫 tooserene 的方法, 这个 tosrin 呢,参数就是我们要啊查看内容的数组,它的作用啊,就是把数组里面这些个元素拼接成一个什么 sing 字符串儿,形成了字符串儿以后呢?哎,我们就可以直接用这个 synthel alt 去打印出来啊。好,那我们来看一下,我把旧数组 ery, 零,还有刚才这个新数组 ery 一它们的内容都打印出来看一看啊 啊,这个数组是不是 a, b, c, d, e 五个元素对吧?但是新数组里面有东西吧,还没有啊啊,它是六个元素,当然这六个元素都是 n 啊,都是 n, 没内容, 那怎么把这个旧数字内容一点一点啊,给他迁移到新数组中去, 哎,这时候你就必须写循环了,我们 urray 零去来一个循环, 每循环一次,那我就把 ari 零,它的第二个元素是不是拿出来复制给新数组这个铜锁引的元素啊?啊,复制给 a r 一的所以零的元素 啊,这个效果呢,就是把旧数组零号元素拿出来,对吧?复制给新数组的零号元素再循环一次,那就是把旧数组一号元素拿出来复制给新数组的一号元素 啊,这么复植一遍以后啊,其实就达到了一个把旧数组元素迁移到新数组的效果。 你看我循环完了之后,我们再打印一下 啊,旧数组不变,对吧?但新数组呢, 减五个元素是不是变成了 a, b, c, d, e? 哎,当然最后一个还是 not, 可以认为它是空着的,对吧? 啊,最终呢,我们可以在新数组里啊,再把最新的元素给他加进去啊,比如说我们又要加一个 f, 对吧?好,那我们就直接写在这了。呃 re 一 它的,所以是不是零一二三四五啊,所以是五啊啊,给这个新的元素 f 啊,最后我们重新运行一下。 好,这是不是才达到了?呃,迁移旧的元素并且添加新的元素,最终新数组我们留下,旧数组就可以不要了,对吧?好,不过呢,从这个例子我们也看出来了, 你要想往这个数组里新加一个元素是很麻烦的一件事情啊。那么这个缺点啊,我们称之为数组,它不能自动的扩容 啊,那我们怎么解决这个问题呢?哎,就是我们今天的这节课的主题啊,就是 every least。 好,接下来我们就来讲这个 air list 啊,它呢就可以用来替代数组比数组方面的一个地方呢,就是这个 air list, 它内部可以去自动的扩容啊,用起来就更为简单。 好,我们把原来这个代码咱们给他抽成一个方法,目的呢是备份一下啊,我们抽方法呢, ctrl r m 啊,然后给方法随便起个名字。 好,这个方法代码我们就不关心了,把它折叠起来。好,我们先来创建一个 every list 对象啊, new 加上它的构造方法 every list。 注意啊,大家一回车的时候 id 呢,会帮我们生成一对尖尖括号,对吧?那这个尖括号呢,大家先把它去掉吧啊,他对我们目前的讲解没有什么影响后面的作用呢啊,会讲啊 啊,先不要那个监控号,这样呢,我们就创建出了一个啊 i release 对象,调用的呢,是他的无餐构造, 如果我们调这个无参购的,它会有一个默认的初始容量, 这个初始容量就是十 啊,也就是他留了预留了十个空位啊,让你可以放多个元素吗?啊,那么如果你调了他的有餐构造啊,比如说我给一个五,那这个意思就说我自己指定了他的什么数数容量啊,就不是默认十了,而是这里指定的是五 啊,这个时候我们的初始容量啊,就是五, 如果你不指定啊,默认的储存容量是十。好,这样我们把这个 air release 对象先创建好,创建好之后呢,我们引入一个局部变量代表它。 好,那对象有了,那接下来我们往里面加一些元素啊,比如说呢,我往这个 every list 里面, 天,咱们我们加元素呢,调一个叫 a、 d、 d, i 的方法来添加元素,我们还是加那几个字符串元素啊,比如说来一个 a 啊,这是一个元素,对吧?再来一个 b、 c、 d, 一按那个 ctrl 加 d 啊,就可以复制一行啊,复制一行。好,我们加了五个元素了吧。好,那接下来如果我再加一个元素啊,我在 a、 d、 d 就会来一个 f, 不怎么样,哎,不用担心啊,因为咱们的 average 的一个特点就是它内部啊,已经封装好了这个扩容的逻辑了,你前面五个元素把这五个空位占满了,是不是容量 接下来放第六个的时候容量不够了,哎,它内部已经帮我们封装好了那个扩容逻辑。 好,那他的扩容逻辑是怎样的呢?啊,内部啊封装了这个扩容逻辑,每次呢他会比原来的容量啊大一点五倍啊,就是按一点五倍来扩容啊, 按一点五倍扩容,那你看我们原来的容量储水容量是多少?是五吧,对吧?那五乘以一点五 好像是一个小数啊,对吧?哎,好像是个小数,那这个小数怎么处理的呢?啊?他是向下 下去整啊,五乘以一点五,是不是最终是一个七点五啊,对吧?啊?七点五向下去整就是直直接舍弃小数部分啊,我也不是做什么四舍五入啊,直接把小数部分舍弃,这容量就变成多少,哎,七了, 能理解吧?哎,那七是不是就可以容纳下新的第六个元素了? 那如果你又往里不断的去加一些元素,那七个空位也不够用了,怎么办?哎,没关系,他继续扩容,还是按刚才的规则七再乘以一点五,对吧?哎,这个就变成多少就变成十点五啊,哎,十点五, 十点五向下去整,是不是就变成十啊?所以它这个扩容就是按五 到七到十啊,以此类推啊,只要不够了,他就帮你去把这个容量啊给他加大啊,让你可以放下这个元素啊。那我们来看一下啊最终的结果啊, 这里我们直接去打印这个 list, 打印 list 对象的时候,它其实内部是调用了 list 的 two screen 方法啊,顾名思义 two screen 啊,就是把这个 list 啊 整个这个整体啊,连通它里面的元素,给它变成一个字母串儿类型啊,拼接成一个字母串儿,一个字母串儿,是不是可以方便的配合 system alt 去打印出来? 平时呢,我们可以把这个 two string 省略掉啊,因为它内部就会帮我们调那个 two string 啊,好,我们运行 是不是可以看到 a、 b、 c、 a、 b、 c、 d、 e、 f 啊,六个元素都加进去了,对吧?好,所以再也不用担心容量不够了啊, i release 内部已经帮我们封装好了扩容逻辑 啊,接下来我们就通过这个网页啊,给大家讲一下这个 earliest 内部是怎么工作的。其实啊, earliest 内部还是一个数组,比如说我们指定这个 earliest, 它的初始容量是八,那么将来啊,它就会创建一个大小为八的数组, 那这里的零一二三五六七,这是数组元素的那个,所以啊,所以好,比如说吧,我先给它里面加八个元素啊,一二三四五六七八 啊,当然这个元素我是为了方便啊啊,一次性添加了,但实际上它是呃调了八次 a、 d、 d 方法加的啊,看一下,加第一个元素,对吧?第二个元素,第三个元素啊,以此类推, 是不是八个元素加满了?加满了,下面是关键啊,比如说我加第九个元素了,那这个数组的容量是不是不够用了?那放不下了怎么办呢?哎,其实就是我们一开始给大家演示的,我得再创建一个容量更大的新数组 啊,看一下啊,这时候你调 a、 d、 d 方法的时候,它就会创建一个新的数字,容量多大呢?哎,就是按我刚才给大家讲的一点五倍那个规则,八的一点五倍 是不是十二呀?哎,他创建出的新数组容量是十二,但是新数组刚开始他这些空位都是没内容的,是吧?那我们是不是得把旧数组的这个元素给他一个个的迁移过来 啊?所以他得把这旧的一二三四五六七八给他迁移过来。迁移过来以后我问旧数组还有用吗?是不是没用了啊?既然没用了,我就用新数组代替掉旧数组。 好,新数组有了,那他的空位也够容纳新的元素了啊,最后再把这个九给他加进去啊,这就是扩容前后啊,他的一个工作流程。 当然如果大家再继续往里面加新的元素啊,比如说十、十一、十二, 好,是不是又放满了?好,你再加第十三个元素时是不是又要扩容了?那就跟刚才类似了, 也会创建出一个更大的数组啊,然后里面呃,把这个旧数组的元素迁移过来,对吧?接下来代替掉新数组,代替掉旧数组,然后最后加入这个新的元素 啊,这就是我们呃, i release 啊,它的扩容的原理。那我这里问大家一下, 有一个问题,就是每次他为什么扩容一点五倍?每次为什么不只扩容一个元素啊?多加一个空位,为什么?哎,这样就可以避免频繁 啊,如果我的新数组只比旧数组大一,那是不是啊?如果我不断加元素的话,他就得不断创建新数组啊?啊,这个成本是比较大的 啊,我们让他的容量比上次大的不止一啊,要大一点五倍,这样就可以避免频繁扩容。

面试官问我, java 范型是什么? string 的 list 能转成 object list 吗?为什么会有类型查找 p e c s 原则?怎么用一条视频,让你不仅知道范型是什么,更知道为什么这么设计。 平时你写代码给 arraylist 里塞东西,都会指定类型,比如 list, 监控号 string。 但你有没有想过, java 一 点五之前没有范型的时候,程序员是怎么火下来的?那时候只能往 arraylist 里塞 object, 什么都能放。 string、 integer, 自定义对象全部一锅炖取出来呢? 全是 object, 你 要用必须强转。更要命的是,你塞进去一个 integer 取出来,当 string 用,编程器不管运行时,直接 class cast exception 炸了。所以范型的第一个作用很简单,就是让编程器帮你做类型检查,避免强转出错。但这只是表面, 范型真正牛的地方是它的设计哲学。你可以把范型想象成一个临时工,它只在编辑期就下班了。通过范型这个临时工,你能在编辑期做三件事, 一是类型安全,编辑器会检查你有没有把错误的类型塞进容器。二是省区强转,你从 list 兼括号 string 里取东西, 直接就是 string, 不 用强转。三是代码附用一个范型,类可以适配所有类型,不用给每种类型写一遍代码。总结一下,范型是 java 提供的一种编辑器类型检查机制, 它让代码更安全、更简洁。听起来这么好,为什么说它是个临时工呢?因为 java 范型有个最反直觉的设计,叫类型擦除。什么意思?就是你写的 list, 监控号 string, 翻译完之后,监控号 string 这个信息就没了,变成了普通的 list, 运行时, jvm 根本不知道这个 list 里装的是 string 还是 integer, 全都当 object 处理,为什么要这么设计?答案是为了向后兼容 java 一 点五、之前已经有无数代码在用 error list 了,如果引入范型之后改了底层实现,老代码就全挂了。所以 sun 的 工程师选择了类型擦除,保证新代码和老代码能和平共处。 但这个设计也带来了一堆反直觉的规则。最典型的就是面试官爱问的陷阱题, string 的 list 能转成 object list 吗?很多人说能,因为 string 继承自 object 错,答案是不能, 为什么?因为如果可以转,你就能往里面塞一个 integer, 然后外面的代码以为这还是 string 的 list, 取出来的时候直接炸,这叫范型的不变性。就算 string 是 object 的 子类,它们的 list 也是两个完全不同的类型,但是序组就不一样, string 序组可以赋值给 object 的 序组,这叫斜变。 为什么述阻可以,但泛行不行?因为述阻的类型信息在运行时还保留着, jvm 能检查你有没有往 string 述阻里塞错东西,检查到了就抛 a race direction。 但泛行不行,类型信息被擦除了,编一期只能提前把路堵死,不让你转换。 说到这,你可能会问,那泛行岂不是太死板了?别急,炸娃引入了通配符来解决这个问题。通配符有三种,记住一个口诀就行, 读用 extends, 写,用 super, 既读又写,就别用通配符。具体来说,第一种是问号 extends, 表示这个容器里装的是某个类型或它的子类,比如问号 extends numbered list, 可以 接收 integer list, 也可以接收 double list, 你可以从里面读东西,取出来都当 number 用,但是不能往里面写,因为变音器不知道这到底是 integer 的 list 还是 double 的 list, 万一你往 integer 的 list 里塞个 double 就 错了。所以这种情况只能读不能写, 记住读,用 extends。 第二种是问号 super, 表示这个容器里装的是某个类型或它的负类,比如问号 super integer 的 list, 也可以接受 number 的 list, 甚至 object 的 list, 你可以往里面写 integer, 因为不管这个 list 实际是什么类型, integer 肯定能放进去,但是从里面读就不确定了。取出来的可能是 integer, 可能是 number, 也可能是 object, 只能拿 object 用,所以这种情况只能写不能读,记住写,用 super。 第三种是单独的问号,表示我不知道这个容器里装的是什么类型, 你可以把任何范型类似的复制给他,但是既不能读,也不能写,除了 no, 这就是 p e c s 原则。 producer extends consumer super 什么意思?如果这个容器是生产者,你要从里面读东西,用 extends。 如果这个容器是消费者,你要往里面写东西,用 super, spring, guava 这些框架的原码里到处都是这个原则,你看懂了这个,就能看懂它们的 a p i 设计。除了这个范型,还有两个经典的坑。 第一个坑是运行时拿不到泛型类型,你写了个泛型类 box 兼括号 t, 想在构造方法里知道 t 是 什么类型,直接 t 点 class, 或者用反射做不到,因为类型擦出,运行时 t 已经变成 object 了, 怎么办?老老实实传个 class 对 象进去,别想着耍小聪明。第二个坑是不能创建泛型数组, 你写 new t 序组或者 new list 的 监括号 string 序编辑器直接报错,为什么?还是因为类型擦除?序组本身是斜变的,会导致类型不安全。如果你真需要,只能用 arraylist 代替或者创建 object 的 序组再强转,但那样就失去了类型安全。开始面试真题环节。 第一问,什么是 java? 泛型泛型是 java 提供的一种编一期类型检查机制,允许在定义类接口和方法时使用类型参数,从而实现代码附用和类型安全。 泛型的本质是编辑器的语法堂,运行时会被擦除。第二问,什么是类型擦除?为什么要这么设计?类型擦除是指编辑器在编辑时会把所有泛型类型参数替换成它的字节码里没有泛型信息。 这么设计是为了向后兼容 java 一 点。五,之前的代码,保证新老代码能互相调用。第三问, list 监控号 string 能转成 list 监控号 object 吗? 为什么不能?虽然 string 是 object 子类,但 list 监控号 string 和 list 监控号 object 是 两个完全不同的类型,这叫范型的不变性。 如果能转,就能往里面塞 integer, 导致类型不安全。第四问, p e c s 原则是什么? p e c s 是 producer extends consumer super 的 缩写。 如果从容器里读东西,容器是生产者,用 extend。 如果往容器里写东西,容器是消费者,用 super 这个原则保证了类型安全和最大灵活性。第五问, 为什么不能创建犯行述阻?因为类型擦除犯行述阻在运行时类型信息会丢失,但述阻本身是邪变的,会导致类型不安全。所以 java 直接禁止创建犯行述阻,避免运行时出错,怎么样? 这下彻底清楚了吧!如果这条视频帮到了你,别忘了点赞收藏!你还遇到过哪些搞不清楚的 java 知识点评论区聊聊,我们下期见!

下面我们来看一下立扣的四十九道题目,字母异位词分组看一下题干,给你一个字母串的输入,请你将字母异位词组合在一起,可以按任意顺序返回结果列表,那这边有一个词叫做字母异位词,什么叫做字母异位词呢?我们可以把我们的这个输入拿过来看一下, 有这样的一个输入,那最终的结果,我就拿一个列表出来啊,就拿一个列表出来看一下,拿一个列表出来,它是这样子的一个,那我们能看到它有什么特征?它都是由三个 元素组成,对,三个字母组成,然后他的组成是相同的,对不对?他的三个元素是一样的,那他只是通过了重新的排列组合得到了一个新的字母串,那我们称通过相同字母重新排列组合得到的字母串,就叫做字母意味词。 字母异位词指的是我们的相同元素通过排列组合啊,然后通过排列组合得到的字母串啊,就叫做字母异位词。然后给一个案例啊,就是这个样子的 看一下,就是这个样子。好,那么它的本质我们能看到的是什么?就是它的字母,它组成是完全相同的,那它的顺序是可以进行排列组合是不同的,对不对? 好,那我如何要去做这道题目呢?我们来看一下,它就是通过字母意谓词,把字母意谓词的一组放到一起,对不对?比如说 e, a t t a t a n, t a n, 不是 放在一起的,那我就另起一个列表,对不对?我另开一个列表,那 at e, 是 的,那我就放进去,我这个列表对不对?那他的,那我这是不是在说的过程当中,我是不是就是在已经进行一个分组了?我如果把它通过一个唯一的特征,那我就放到一个组里,特征不同,我就另开一个空列表,对不对?去放它,是不是这样子? 那我如何去做呢?是不是就是我需要去将每组的意谓词找到一个共同特征啊?那找到一个共同特征,找到一个唯一的标识,去标识这么一个字母意谓词这一组,然后如果说他的他是一样的,那我就把它放到一个组里面,对不对? 那我如何去做呢?我们之前有讲到过一个数据结构, map 的 数据结构,大家还记得吗?它是 key value 的 结构,之前一直在讲这个 map set 这种哈希表的结构,哈希表的这个数据结构对不对?那我们用的最多的,其实用的其实挺多的。 map 对 不对? key value 的 结构, 那这边的 key 我 放什么呢? key 是 不是就是放我们的特征标识,对不对?是放我这一组,能够识别出我能够放到这一组的依据,对不对?每一组异类词我们需要去找到这么一个标识,我的 key 就是 标识,而我的 value 就是 说就是放进去,我就把这同组的异类词放进去, 能不能理解?比如说 at 啊?比如说 a t e 这个 a t e, 我 通过某种 key, 我 啊,我 a t e, 因为它前面没有这个 这个 key, 对 不对?那我就是说 a t e, 我 识别到了一个 key, 那 我就另开一个这个列表,然后放,把这个 a t e 放进我的 value 里面,对不对?那我就放进去了,那放进去之后呢? 放进来了之后呢?放进来了之后,下面一个是 e a t 对 不对?那我 e a t 根据某种 key, 某种标准看啊,我这个 key 跟 e a t 是 符合的,一样的,那我这个 key 跟 e a t 是 符合的,一样的,那我也放进我的列表里面,从而 key 也是一样的一个操作,放进去,最后得到了这么一个 value 的 列表,是这样子的,对,可不可以?是不是可以?那如何去找这样的一个唯一的标识去?标识能够作为我们分组的依据呢? 怎么做?这边我们给出两种解决方案啊。第一种解决方案就是利用排序法,那么排序后的次序串就是作为我的 key, 作为我的键啊,通过排序啊,这个排序跟那个排序可不一样啊,这个排序就是说我通过排序去标识我的 key, 能理解吗?就比如说它的这个 a t e e a t t e a, 它排序完应该是 a e t 对 不对?应该是 a e t, 那 我就拿这个 a e t 作为我的 key 啊,就拿我的 aet 作为我的 key, 然后去查找啊,我的 aet 跟排就是拿 ate 拿过来排序,那排序跟 aet 一 样吗?一样,那我就放进我的 byte 值里面,那 eat 排完序也是 aet, 那 么也放进我的 byte 值里面,那如果是 tan 呢?那是不是 an t? 那也放进。呃,看一下 key 一 不一样,跟 aet 一 样吗?不一样,那我就另开一个,对不对?那我就不放到我的这个 value 这里面,不放到我 aet 相应的 value 这里面,可不可以?是不是可以的?好,如何去实现?我们来看一下。首先我要去创建哈希表, 接下来我的 key 是 放我排序后的字串, 而我的 value 放的是,而我的 value 放的是意谓词。每组意谓词,也就是意谓词的列表,也就是对于我的结果集,意谓词列果列表的结果集。接下来我们去进行一个负循环, 在这个做之前,我需要将 string 类型改成 char 序组啊,因为它排序它是不能够,因为 arrays 类的 sort 方法它只能够排序组啊,它 比如说 int 序组啊, char 的 序组啊,啊,字母序组它不可以排 string 类型啊,它就是字母序组类型,它是会翻译包错的,所以我前面必须得给它转个类型, 就叫它 char area, 我转个类型转完类型之后呢?然后我再去进行 sort, 然后我对字母数组进行排序之后,它最终的因为它意味词的排序结果是相同的,那我就把这个作为我的 key, 对 不对?就把这个作为我的 key, 那 我需要去定一个 key, 定一个 key 值,去接收我的 string 类型,接收我的程序之后的结果。 然后我们做一个判断,如果说我的 key 它不存在于 contents key, 如果我的 key 它不存在于,如果我的 key 它不存在于我的哈希表当中,那我就出示画我的空列表,我就出示画我的空列表, 那如果说存在呢?如果 key 存在,那我就需要去把它给放进去,对不对?我 get a key, 然后呢?去把它放进我的,放什么 是放 s 啊?对吧?放进去,然后我直接去天津添,把这个放进我的这个哈希表当中,把我的 key 放进,把我的 s 放进相对应 key 的 value 值当中,对吧?然后最后我们 return。 聊天的时候要注意,因为我需要去把这个重新包装一下。重新包装一下, 为什么要重新包装一下呢?因为因为我的 map 点 values 就是 我的 map 点 values, 我 它的返回类型是,它的返回类型是 collection 类型 是 collection 类型。我需要把它包装成。需要把它包装成 list 啊,非要把它包装成 list 才能够进行返回,因为它最终需要的就是 list, 对 不对?好,然后我们这样子就完成了。我们来看一下, 看一下对不对?不对,是不是少了一个? ok, 这样子就完成了,这样子就完成了。那 string 拼错了, s, e, r, n 键, string 拼错了,这样子就可以了,对吧?那么有没有什么其他的方法呢?有没有什么其他的方法?这种方法就是说我将字母串进行排序,对回排序后了的字母串作为唯一的标识,然后再进行一个分读。还有没有其他的做法? 这样子是可以的,这样子也是可以的,都是对的。然后这样子也是不错的一个解法,对吧?那还有什么其他的方法? 这边我再介绍一种方法。这边我用,这边我就不删了,我就用 python 写吧,我用 python 写。呃,第二种方法叫做计数法, 什么意思呢?嗯,这边用的应该是这个计数法。计数法它的意思就是说我去统计每一个字母串中二十六个字母对不对出现的次数,然后用计数的结果作为唯一的标识。什么意思啊?什么意思?就比如说, 比如说是 e, a, t 啊,比如说 a, b, c 吧,比如说 a b c 和 b c d。 嗯, b c, b, c, a, a, b c 和 b c a。 它我最终它我需要的是我给它一个数组,我给它一个数组,我给它一个列表,存放我的这个 a 到 z, a 到 z 的 这个计数。比如说零,刚开始都是初设都是零,零,零,一直到 a 到 z 都是零啊? 比如说这是 a, 对 吧? a, 然后 a 到点点点点零, a 到 z 都是零, a 到 z, 它都是零,对不对?然后这是 b 的 位置,然后这是 c 的 位置, abc 它都是零,那所对应的我这个 a、 b、 c 呢? a、 b、 c 的 话,是不是就是这个位置记一,这个位置记一,这个位置记一,也就相当于我拿一个列表出来去标识唯一标识我的这个 a、 b、 c, 对 吧?唯一去标识我的 a、 b、 c, 唯一去标识我的 a、 b、 c, 那 这个其实也是一样的, b、 b 的 位置记一, c、 c 的 位置记一,然后 a、 a 的 位置记一,对不对?可不可以这样? 是不是可以这样子?然后将唯一的这个标识去标识我的 abc, 标识我的 bca, 那 当这个标识相同的时候,是不是就可以相当于它计数的结果相同的时候就是什么?我就把 abc、 bca 放到一组里面,那其实这样的一个思路其实也是什么?先要也是要使用哈希表进行这个分组,对不对?那前面不同的是什么?不同的其实就是它标识的 不一样,对不对?它标识的不一样,它用什么去标识?是不是用技术的结果去标识,对吧?那我们这边来写一下,用技术的结果去标识,我就把它叫做 enigma, enigma, 因为我需要一个结果 enigma 去存放我的,去存放我的结果,去存放我的结果。 首先我需要去循环我的给的 strings, 它用的是冒号。首先我要出水画长度为二十六的列表,对不对?因为我 a 到 z 嘛?而且因为它是小写啊,因为它是小写,我们可以看到它的只只包含小写的,只包含小写的。那后面我会说,如果它有大小写怎么办? 我先出水画一个列表,出水画一个列表, 抽象一个列表,然后呢?我去便利去计算它的每一个位置的缩影啊?每一个字母的缩影相当于什么意思呢? 每一个字母的缩影,比如说 a 对 应的是零, b 呢?对应的是一,这是位置啊,这是缩影。字母啊,也就相当于我将字母, 我将字母去映设为,我将字母映设为缩影,我将字母映设为缩影。 b 到 b 是 一,对吧? c 是, 然后一直到又又又调到那个东西, z 就是 我的二十五,对不对? z 就是 二十五,那如何去进行这个?我怎么怎么怎么去做呢?我怎么去做?我这边把 s 里面每一个元素都取出来,然后进行便利,然后我要做的操作是将字母映设为缩影,如果说我取出来的这个值, 然后我再到列表里面去找,找到了之后我加一,是不是这样的操作?那我怎么怎么去做呢?是不是我可以利用它的阿斯玛值?如果说它因为 a 的 阿斯玛值是九十七,对不对? a 的 阿斯玛值是九十七, 那如何映射为零呢?是不是减去九十七?那 b 是 不是减 b 的 话是九十八?减去九十七就可以了,然后 z 的 话减去九十七,二十五,是不是可以这样子?这样子就可以好做一些。 呃,我们拿当前位置的 asc, 当前元素的 asc 码值减去 九十七啊,或者说减去当前就是减去第一个值嘛?第一个值是 a 嘛?就九十七的,就 a 的 asc 码就是九十七,对吧?然后如果说它,比如说我 count 目前,比如说是 a, 对 吧?那也就是说我拿 e 的 位置,拿 e 的 位置,也就是 a 的 位置,对吧?字母 a, 那 就可以在这个位置就加,等于就加一嘛,我这个位置就计数为一嘛,对吧?然后如果说它出现第二次,那我就 二次出现的话,就是再加一,也就是一加一等于二,是不是这样子,对吧?那么这边后面,那我计数完了,对不对?我拿到了一个列表,那这么一个列表,我要将它作为我的 key, 我 要作为我的 key, 有 一个条件 t 的 话要作为作为,要有一个条件,就是它必须,它是不是必须得可哈希啊,对不对?那可哈希的话,我的列表可哈希吗?列表不可哈希,对不对?而什么可哈希在 python 里面是不是原组可哈希啊,原组是不可变的,对不对?那我是不是需要去转换一下它的类型? 就要转换一下它的类型,我需要把它变成 tempo 类型,将我的 count 变为这样子的话,它作为我的 key, 这样子 tempo 类型,它作为我的 key 是 可哈西的,那它就可以作为我的 key, 作为我的键, 是不是?那如果说我的 key not in 我 的这个列表里面,不在我的这个结果集里面,那么跟 java 是 一样的做法,就刚刚的呃,排序法是一样的做法,我就把它进行一个抽象,一个空列表, 那如果说它存在啊,这么一个 key, 我 找到了这么一个 key, 那 么我就加进去, 用 append, append s, 对 不对?这个 append s 我 把它加进去,然后最后 return 一下。 return 的 话要注意一下它的类型啊,应该也是 list, 因为我的 erratic 点 values, 它最终它这个结果拿出来的这个结果的类型你还记得吗? 它拿出来的类型是什么?它拿拿出来的类型应该是,比如说我 type 一下, type 一下应该是,应该是 ticketing value, 有 意义。 ticketing values 类型应该是 ticketing values 类型,所以说这个类型它不符合我最终要输出的列表类型啊,最终的输出的列表类型,所以说我需要把它转一下类型,这样子就可以输出了,对不对?好, 那这两个有这样子就写完了,我看一下提交一下,可不可以啊? ok 的,是可以的,是可以的,这样子是可以的。 ok 的, 那有这两种方法,这一种方法是计数法,还有一种用的是加法,写的是排序法啊,一个是用我的这个 字母串排序啊,排序后的字母串作为唯一的标识,然后再进行分组吧。那还有一种方法就是使用我的啊,统计每个字母串当中二十六个字母他的出现的次数,然后用计数的结果作为我的唯一的标识,然后用这个标识去作为我的,就作为我的 key 嘛,然后再用计数结果去进行分组,作为分组一级进行分组,这样的方法都是可以的,都是可以的。 那有时候哪个是最优解?那个是最,那要看情况。那其实说如果说你的数据量体量很大的话,那我觉得我更推荐于啊。第二 啊,技术法啊,我更推荐于技术法,因为如果说他的因为他的复杂度跟他的时间复杂度是要比排序法要来的低的,因为他技术技术法的时间复杂度应该是 o n k, 他的效率更高啊,他效率更高,因为因为加法他他这种方法就是说不是加尾排序,是排序法这个操作,他多了一个排序啊,他多了一个排序的这个复杂度,时间复杂度,因为他有一个 k log, k 的 复杂度多了一个额外的开销。所以说如果说体量数据体量比较大的话,我觉得 python 这个技术法是不错的,还是可以,还是略胜一筹,效率更高。那这边有几个问题啊, 如果说题干,因为他题干说了嘛?他说仅包含小写,我刚刚题目写的时候我也说仅包含小写,那如果说因为词当中有大写怎么解决呢?啊?有可能会问你啊,如果说他他要大写呢?他有大写又有小写,那怎么去区分呢?比如说我输出是这个样子的,对不对啊?我就拿我就拿这边, 就比如说我现在我,我是 a, b, c, a, b, c 这样子呢? 如果是这样子呢?如果是 a, b, c, a, b, c 这样子,那如果有大写字母,呃,然后要求是,呃,就是说这两个大写字母是算意味词的,就是说 a、 b, c 也好,三个 a、 b, c 都是大写也好,它们是算意味词的,它们算意味词。那我怎么去进行判别呢? 我是不是可以怎么做?我是不是可以先把它们全部进行小写,对吧?我要把它变成小写,我把它键变成小写了之后将所有大写字母转化为小写之后再进行判别,判别完了之后是不是就可以了,对不对? 对不对?是不是可以?就比如说如果是这种,这个如果是 python 里面,我在哪边要进行变化?比如说计数法当中我要变什么?比如说计数法当中我要变什么?计数法当中我这个大小写的话是在 在这边,是不是在这个后面?或者在这边,在这边要加一个 lower 的 操作点 lower, 用 lower 函数去将所有的大写字母转化为小写,然后再减,减了之后就可以了。然后还是不管是大写的还是小写的,我都已经转化为这个 c, 我 已经全部转化为小写的了, s, 对 吧? 当然这边要改一改了,这边不是 s 了,这边的 s 应该要变,比如说,比如说要变成 s e, 要变成 s e, s e 去接收 lower 函数所变成的小写字母,然后再去便利小写字母,然后便利小写字母之后还是对应的一样的缩影值,还是二十五的缩影,对不对?然后如果说是 java 呢? java 在 哪里变? java 的 话就是在,嗯,在排序之前还是排序之后变啊?那它好像对在排序之前变,对吧?用 character 它变成小写了,对吧?然后呢,我要去进行一个变写,变,把它呃小写,那小写的话就用 character 类当中的静态方法 to lower case, 用 to lower case 去进行小写,那小写完了之后再进行排序,对吧?这样子是可以的。 那么如果说这个是大小写不敏感,那如果说大小写敏感呢?也就是说如果我的 abc 和 abc 就 大小写,它,比如说 abc 和 abc 它不认,也就是说它大小写敏感,它不算异位词,它们两个根本就不算异位词,怎么办?那我就不需要转化为小写了,大小写对不对?就是小写和大写不需要转化了,那我直接处理是不?直接处理怎么处理? 我这个怎么处理?因为大小大小写它不,它敏感,那我就怎么做。是不是我需要把大,比如说大写是二十六位,大写是二十六,对吧?小写也是二十六位, 那 a 到大写的 a 到 z 是, 比如说我要把它变成五十二位,对吧?我把它变成五十二位,那,那这边要改一改了,对吧?是大写的 a 是 零,大写的 b 是 一,大写的 z 是 二十五,然后小写的 a 是 从几开始?是从二十六开始,然后一直到小写的 z 是 五十一,对不对? 对吧?这样子的话,我就把也是赋,还是一样的思路,就是中间有一点小变化,就是把赋串啊,讲字母映设为缩影,把这个缩扩展它的数组的长度啊,扩展至五十二位,然后我再去进行处理,然后还是一样的。就是计数嘛,对吧?那这个排序法怎么去做呢? 排序法怎么去做?那排序法其实也是一样的,就是排序法,就是它根本就不需要直接对原原字图去进行排序嘛?也是一样的排序,那排序它如果说相同,它根本就不需要做任何操作,对吧?如果它相同,那我就 ok, 那 我就可以,那如果不同,那就 pass, 就是 一样的。那就是说开一个空列表,对吧?其实这个就不需要动了,就是它根本不需要动, 因为它显示的不同,那它就肯定会识别出,那我就不是,我这个 key 就 不一样,那 key 不 一样,它肯定不会分到一个组里面,对吧? 所以说这是两种方法,也就是说他提干当中意味词如果他有大小写之分,并且他这个大小写,他大小写是否敏感?他敏感怎么做?不敏感怎么做?他有不同的这个解决方法。好吧,这个是需要去注意到的,所以说这这个题目我采用了两种方法。综上,我这采用两种方法,第一种是排序法,用的是 java 来写的。第二种是呃技术法,用的是 pass 来写的。 而排序法他其实两种方法都采用了哈希 map 啊,就采用了 map 的 这样的一个数据结构去做, 因为它的每一组意谓词我都找到了一个唯一的标识作为 key, 然后呢,使用 key 进行一个分组啊,用 key 进行了一个分组, 排序法呢,是用字母串的排序,用字母串排序,然后排序后的字母串作为唯一的标识,然后进行分组。而我的计数法使用的是我的 统计这个技术结果啊,统计每个字母串所出现的字母,也就是字母出现的次数,然后用这个技术的结果作为一个唯一的标识,然后去进行分组啊,所以说要了解这两道题目啊。

今天我们给大家介绍另一个在 java 里面经常使用到的一个数据结构,这叫 link 的 list, 它是通过一种链表来实现的,我们看一下这个链表它是长成什么样的,就像我们这个生活当中一个铁链子一样的,那这个 它属于一个节点,就是我们可以向里面存数据的一个地方,比如说有一个绳子也好,或者铁链也好,连到另一个节点上面, 然后这个这个节点又把它穿到另外一个节点,当然你从后面也可以向前面来走。这种链表的这种形式呢,最底下我们给他存的是数据,他比较适合,比如说我们想向中间添加一个元素,比如说这是一个 h, 想添到这个 a 和 c 之间, 我把这个给他剪断,把这个也给他剪断,把这个给他哎放到这,把他连到这来,同样这个让他指向这样,然后把这个再指到这里面来, 这样的话我们就很顺利的在这个 a 和 c 中间给他插入了一个这种节点啊。删除也是一样,如果你想,比如说我把这个给他删掉,那你就把它剪断,剪断之后把原来这个再恢复过去。 所以呢这种 link 的 list 他 这种添加和删除是非常方便的,但是他如果要查找的话,可能就比较麻烦。查询的时候呢,你必须从这个头部,然后一个一个的这样往后走,走走走,如果你要找到在 在中间或者靠后的位置,那你可能要找很多才能把它找到。这种修改比较频繁的场景,你可以考虑用这种叫 link 的 list。

今天我们来给大家讲一讲 java 的 一个数据结构,叫做 arraylist, 实际上在我们的内存空间里,它就是一个连续的空间,然后它被分割开啊,比如说这是一个格子,两个、三个、四个,那我这个呃是一个长度为四的一个数值, 那这个 arraylist 呢?它底层其实是用数值来实现的,它的特点就是我们可以随机的去查询这里面任何的一个值。比如说我这里存的是 a, 这是 c、 b、 d, 你 如果想查这个 b 啊,他其实就是在这数组里面第一、第二、第三个格子,他很快就是可以查到。但是呢这种数据结构他也有他的一个缺点。你比如说我想往这里面中间突然加这么一个值的话,那这个没有位置,那只能你先扩出了一个格子,然后把这个 d 往后挪一个位置,然后这个中间就出现了一个空格。比如说你加了一个 m, 那这样的话你就会需要把很多很多的这个元素啊都开始移动,或者你删除也是一样。比如这有一个你先把它删掉,删掉之后呢,这个后面的都要向前移动它,这样的话它会损耗很多的性能啊。 但是它查询起来的确是比较快,它属于一种集合的这种类型啊,你要存多个元素的时候,我们就要用到这种额外的这种数据结构了。

好,现在已经四点了,我把所有的文章都已经基本上过了一遍啊,先说两个问题啊,一个解释了一个问题啊。首先大家别关心这个包中有说这个 直覆盖残留在里面,首先这个东西是不就是说,嗯,它是有可吸收和不可吸收的两种,但是无论哪种你都不能以此为借口作为留在里面的一个理由,明白吧?就哪怕是可以吸收,那你也不能说它可以吸收我,就我就没有节制的没有规则的去把它遗留在里面, 好吧。啊,首先就是说我查询了一些资料啊,在里面报告里面有说到这个大家应该可以放心,就说可吸收再生氧化这个东西有记录的使用记录,没有相应的条码,都在有效期里面,所以说这个现在目前看来是没有什么太大的疑问的。 好,那第二个问题是什么呢?这个中心静脉压 cpb 就是 说我不说这个技术的问题啊,就是说这是一个, 这是一个知情同意书。不是术前吗?术前知情同意书,他有病情需要需要干嘛?需要做些什么?在书中签签字的。那他有个检测 c b p 的, 他勾了,当时就说之前万一只有一个人,他这个单子,他这个基础单页 c b p 都是空的,这个指的其实很挺重要,但目前来看没有找到任何的地方都找不到他在整个书中这个蛛形静脉压是一个什么样情况。 好,我先说这两点,然后的话就是那个止血纱布的话,就是就是,我我我,我猜测应该这个问题不大,因为他是有据可循的,是没有什么太大的争议的。好吧,大家不要被。嗯,不要被误导。好吧,好想接下来我再说另外一下个视频,好吧,太棒了,谢谢。