为什么要扩容

截屏2020-04-02 下午10.39.38.png

尽量避免重复!这是根本原因!因为重复就会造成链表的长度增加。链表的查询是线性的难度,长度越低,越快!

如何扩容

注意:扩容了,必定要重新排列各个元素。重新计算所有元素的hashCode。
扩容不是简单的长度翻倍,最好是个质数!
在什么时机扩容?
这是最根本的几个点。

截屏2020-04-02 下午10.47.29.png

实现

重排列方法

  1. resize(size) {
  2. this.limit = size;
  3. const storage = this.table;
  4. this.table = [];
  5. this.count = 0;
  6. storage.map(
  7. val => {
  8. if (val) {
  9. if (val.key) {
  10. this.put(val);
  11. this.count++;
  12. } else if (!val.key) {
  13. //这里我觉得很不好,源于假如如今的链表长度为0呢?浪费性能了。
  14. //所以我又修改了前面的删除操作,增加了判断删除后的链表长度为0 就设table
  15. //的对应节点为null值
  16. let current = val.header;
  17. while (current) {
  18. this.put(current.data);
  19. this.count++;
  20. }
  21. }
  22. }
  23. }
  24. );
  25. }

扩容的逻辑

  1. largerResize() {
  2. const test = this.count / this.limit;
  3. if (test > 0.75) {
  4. this.resize(this.limit * 2);
  5. }
  6. }
  7. smallerResize() {
  8. const test = this.count / this.limit;
  9. if (test < 0.2 && this.limit > 20) {
  10. this.resize(Math.floor(this.limit / 2));
  11. }
  12. }

这两个方法我都最后决定学老师的意思,全都傻瓜式地放到各个增加或删除的操作的逻辑里了。

根源就是this.count的改变,我现在有种想把this.count的方法用Object的set方法实现,进行数据劫持,岂不更好?

还有一点强迫症,对于每次添加然后进行largerResize的方法,我没意见,性能相关。但是每次删除,都要进行减小扩容的判断逻辑,我觉得很容易浪费性能。
当然,浪费性能的情况说的是前期,数据量小的时候,删一个就会重排,删完,加一个也可能会重排,所以我根据老师的指引,加了个this.limit > 20的限制。但是还是觉得别扭。想想也就是释然了。

这是对人的根本性的不信任造成的,对机器这种傻瓜式的程序,人是更愿意相信的。虽然可能前期删除会损耗性能,造成不必要的重排,但是更智能的,而且前期为什么缩小?数据量太小了!所以性能会多做无用功,但是不多的!
而且,这本身只是为了,优化内存
我的鼠目寸光让我觉得,这也为了后面扩容时数据的重排的损耗,因为数据量少而变小了。除非数据的量未来会超出我的那个假设的条件的边界。