当第一次声明table的时候,通过#符号来获取长度就按照上图源代码判断。原文链接
tab = {1,2,3,nil,nil,6}
-- #tab为6
如果后续插入例如
tab = {1,2,3,nil,nil,6}
tab[7]=7
则会进行Rehash导致#tab结果从6变为3。原文链接、例子
Lua的Table的内存结构主要分array part和hash part,它们俩的内存大小是动态变化的,如果空间不够就需要分配更多的空间,如果空间利用率太少就需要缩减内存,这个过程叫做rehash。
现在来看看rehash是怎么样的过程。
rehash内部,主要是做了以下几件事:
a.计算array part的key的数量
b.计算hash part的key的数量
c.计算新设的key之后array part部分的数量,
d.计算一个新的array part部分需要分配的内存大小
e.resize。(大概过程如上,后面是每个步骤的细节,如不需要了解,可以跳到最后了。)
static void rehash (lua_State *L, Table *t, const TValue *ek) {
int nasize, na;
int nums[MAXBITS+1]; /* nums[i] = number of keys with 2^(i-1) < k <= 2^i */
int i;
int totaluse;
for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */
nasize = numusearray(t, nums); /* count keys in array part */
totaluse = nasize; /* all those keys are integer keys */
totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */
/* count extra key */
nasize += countint(ek, nums);
totaluse++;
/* compute new size for array part */
na = computesizes(nums, &nasize);
/* resize the table to new computed sizes */
luaH_resize(L, t, nasize, totaluse - na);
}
笔记
1.虽然正整数作为键值的数据写入lua表时不确定是写入了数组还是散列表中,但 0 和 负数做 key 时是肯定放在散列表中。