为什么要扩容
尽量避免重复!这是根本原因!因为重复就会造成链表的长度增加。链表的查询是线性的难度,长度越低,越快!
如何扩容
注意:扩容了,必定要重新排列各个元素。重新计算所有元素的hashCode。
扩容不是简单的长度翻倍,最好是个质数!
在什么时机扩容?
这是最根本的几个点。
实现
重排列方法
resize(size) {
this.limit = size;
const storage = this.table;
this.table = [];
this.count = 0;
storage.map(
val => {
if (val) {
if (val.key) {
this.put(val);
this.count++;
} else if (!val.key) {
//这里我觉得很不好,源于假如如今的链表长度为0呢?浪费性能了。
//所以我又修改了前面的删除操作,增加了判断删除后的链表长度为0 就设table
//的对应节点为null值
let current = val.header;
while (current) {
this.put(current.data);
this.count++;
}
}
}
}
);
}
扩容的逻辑
largerResize() {
const test = this.count / this.limit;
if (test > 0.75) {
this.resize(this.limit * 2);
}
}
smallerResize() {
const test = this.count / this.limit;
if (test < 0.2 && this.limit > 20) {
this.resize(Math.floor(this.limit / 2));
}
}
这两个方法我都最后决定学老师的意思,全都傻瓜式地放到各个增加或删除的操作的逻辑里了。
根源就是this.count的改变,我现在有种想把this.count的方法用Object的set方法实现,进行数据劫持,岂不更好?
还有一点强迫症,对于每次添加然后进行largerResize的方法,我没意见,性能相关。但是每次删除,都要进行减小扩容的判断逻辑,我觉得很容易浪费性能。
当然,浪费性能的情况说的是前期,数据量小的时候,删一个就会重排,删完,加一个也可能会重排,所以我根据老师的指引,加了个this.limit > 20的限制。但是还是觉得别扭。想想也就是释然了。
这是对人的根本性的不信任造成的,对机器这种傻瓜式的程序,人是更愿意相信的。虽然可能前期删除会损耗性能,造成不必要的重排,但是更智能的,而且前期为什么缩小?数据量太小了!所以性能会多做无用功,但是不多的!
而且,这本身只是为了,优化内存。
我的鼠目寸光让我觉得,这也为了后面扩容时数据的重排的损耗,因为数据量少而变小了。除非数据的量未来会超出我的那个假设的条件的边界。