粉丝1423获赞1.4万

今天呢,我们通过原码来看一下 a realist 的扩容机制。首先我们看一下第一种,我默认又一个 a realist, 这这个时候它的大小是多少呢? 我们点到 a realist 里边,可以看到有这么一个副值语句,可以看一下啊,这个值是一个空的 object 的一个数组,哎,再看看 element state, 他说 a realist 的一个字段,可想而知他就是 a realist 中用来存储我们数据的核心字段。 再回到这里,我们可以看到 a realize 的默认构造函数,他就是创建了一个空的数组,这个时候还没有容量。这个时候当我插入第一个元素的时候,那 a realize 里面会发生什么变化呢?我们一起来看一下。可以看到,首先他会去检查我们当前 存入这一个元素需要最小的容量是多少,及我们数组容量够不够。这里的塞子加一就是我存这一个元素最小需要的容量塞子,因为表示是我已经存入的元素,这里你再理解一下。 我们继续往进追,可以看到,在判断当前容量够不够的时候,我们需要先计算当前的容量吗?所以我们来看一下这个 calculator company, 它是传入了我们当前的 element data 和我们最小需要的容量大小。可以看到,在计算大小的第一步,它会判断我们 element date 是不是刚才默认构造函数里边的那个空数组, 如果是的话,那他会在我们需要的最小容量和默认容量里边挑一个最大的返回可以看一下这个默认容量大小,他是十。可以看到, 按照我们刚才的步骤,我们扭一个 realist 以后,添加第一个元素的时候走到这里,那么它的 main captain 就是一, 默认个默认大小就是十,那么这里他就会返回一个十。可能有人会疑惑,这里如果每次像我上面那样写 ad 的时候,那他的命 capt 永远都是一啊,他干嘛还要再去和默认支笔大小呢? 因为命他有时候不一定是一,比如我调了 addio 方法以后,那我里边有多少个元素,那我这个命 captain 他就是多少。如果 animalty 的不是我们默认的空数组的话,那这里就是我们需要最小的大小,是多少就返回多少。 当需要的最小容量计算完以后,就开始到这个里边去检查容量够不够了。我们进来看一下第一个他会给这个 modcont 加加 modcond, 它主要注意 用来集合被修改的次数,比如说我们添加了一个元素,也算是被修改,所以这里要进行一个记录。接下来会进行一个判断,就是我们当前需要的最小容量如果大于数字的长度,那证明容量不够了,就需要扩容,否则不需要扩容则什么都不做。按照这种写法, 我需要的最小容量应该是十,而数组长度是零,所以就会进行第一次扩容。我们来看一下是怎么扩容的, 我们看一下 gru 他是怎么扩容的。首先呢,他会记录旧数组的大小,然后他会计算新数组的大小,新数组的大小是旧数组容量加上旧数组的一半,因为这个 按位计算往右移位的话是除以二。然后他会去判断,如果新容量没有我最小需要的大,那则取我最小需要的容量大小作为新的 容量,可以看一下新容量如果大于 max river size 的话,则会进行一个 huge competit 的一个操作。这里可以看一下 max river size, 它最大值是 inter 最大值减八,那么它就会进行一个 huge competit 的一个操作。入餐呢是我们需要的最小容量。 我们来看一下这个 huge cavity 里边是什么。第一个呢,就是说当我们需要最小容量,如果小于零的话,他会抛出一个内存已满的异常。 这里为什么是小于零呢?因为我们能申请到 arrival 数组最大的值是 inter 的最大值,当 inter 的最大值超过 inter 最大值的时候,他就会变成一个负数, 可以看到他变复数的过程是一个未运算。如上图所示,接下来就会判断,当我们需要的最小容量如果大于 max river size 的话,则返回 inter 的最大值,否则返回 max a river size。 所以这里要纠正一点,就是我们的数组最大空间是 inter 的最大值,而不是 inter 的最大值减八。 那么问题来了,第一个有人可能会很好奇, max arrival size 为什么是 inter 最大值减八呢?大家可以先想想我下个视频详细和那个微运算一块讲吧,不然太长了。 最后我们再来看一下这个扩容函数,新容量正常大小就是在旧容量的基础上增量他自身的一半。到这里呢,就是我们的数组容量已经扩好了,足够支持我们插入新的元素了。 最后呢,我们回到这里,可以看到我们给数组中插入我们的元素塞子加加,那塞子最开始比如说是零的话,对吧?那我们给第一个插入元素,然后塞子的值变为一,最后返回成功。 到这里就把 realist 扩容的整个过程讲完了,接下来我们看一下这种,就是我 new realist 的时候,里边给了一个固定的大小,可以看到这里的话,他会直接给厨师画一个对应大小的数组。 那么后面 a, b, c, d 的插入,大家可以根据我前面的代码,然后我自己再捋一遍这里呢?当插入 d 的时候他会进行一个扩容。通过上面的一些分析,我们可以看到 river 他默认的大小是十, 并且呢他在扩容的过程中会有数组的拷贝,所以如果我们对于性能有足够强严格的要求的话,那我们可以根据实际情况,尽量在初始化数组的时候给他一定的大小,从而避免不必要的频繁扩容。