Lua源码:向table内新增元素及rehash过程

Lua向表内新增元素(N)主要走的是luaH_newkey函数。其过程大体如下:
根据给定的key计算出应该存放的位置P

  • 如果P处没有元素,直接存放就好
  • 如果P处已经有元素,这时存在两种情况:
    • 在P处发生了碰撞,需要在物理上将N存放到下一个空位,并从逻辑上将N连接到P的链表中
    • 在别处放生碰撞的元素(O)被放到P处,需要将O移到下一个空位,将N存放到P处

在这里插入图片描述
可以看到,无论何处发生的碰撞导致P处被占据,此时都要找到一个新的空位置F来存放新元素N,而当空间已满的时候,无法找到新的F,此时就会触发重散列的过程,调用rehash方法。
在这里插入图片描述
我们知道,Lua的表包括了数组和散列表两部分,这两部分的大小如何分配、整数键的元素是放到数组中还是放到散列表中,都是由Lua自行决定的。这个自行决定的完整过程,就是rehash方法的内容。

Lua分配这两部分空间的原则也很简单,即优先计算数组部分,剩下的部分全放到散列表里。而如何决定数组部分的大小,Lua的作者们在《The Implementation of Lua 5.0》中已经说得很明白了:

  • 数组的空间至少有一半以上被利用(保证空间的利用率)
  • 数组的后半部分内至少有一个元素(避免只要一半空间就能装满却多浪费了一倍空间的情况)

为此,我们在重散列的过程中需要知道:

  • 一共有多少个有效的整数key(value不为空)—— 变量na
  • 这些整数key的分布情况 —— nums数组
  • 所有的key的数量(用于计算散列表部分的容量)—— 变量totaluse

所以,rehash的逻辑也很清晰:

  • 通过numusearray统计数组部分内包含的整数key数量和分布情况
  • 通过numusehash统计散列表部分内包含的整数key数量和分布情况,并得到总共key的数量
  • 通过computesizes计算应该分配给数组部分的空间大小
  • 通过luaH_resize按照之前计算的结果重新分配空间

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值