一,简介
lua表中将数据存放的两种类型的数据结构中,一个是数组,一个是散列表(哈希表)。
二,举一列列子
local a = {}
for i = 1, 3 do
a[i] = true
end
在这段代码中,主要做了如下工作。
1.最开始,lua创建了一个空表
2.在第一迭代中,a[1]为true触发了一次重新散列操作,lua将数组部分的长度设置为2^0,即1,散列表部分仍为空。
3.在第二次迭代中,a[2]为true再次触发了一次重新散列操作,将数组部分长度设为2^1,即2.
4.最后一次迭代又触发了一次重新散列操作,将数组部分长度设为2^2,即4。
三,原因
只有三个元素的表会执行三次重新散列操作,然而油100万个元素的表仅仅只会执行20次重新散列操作而已,因为2^5 = 1048576 > 1000000。但是,如果创建了非常多的长度很小的表,这可能会造成巨大的影响。
四,优化
如果你很多很小的表需要创建,就可以预先填充以避免重新散列操作。比如:{true,true,true},Lua知道这个表油3个元素,所以直接创建了3个元素的数组。类似的,{x = 1,y = 2,z = 3},Lua会在其散列表部分中创建续航都为3的数组。
所以,当需要创建非常多的校标时,应预先填充好表的大小,减少解释器被动地进行重新散列操作的过程。
五,取长度操作
print(#{10,20,nil,40}) --输出2
这个表看上去是一个数组形式的表,三十由于键值为3的位置对应的数据是nil,所以只有前面两个键值1,2被认为是组成了一个序列。因此,对这个表进行取长度操作时的结果为2。
print(#{[1] = 1,[2] = 2}) --输出2
print(#{[1] = 1,[2] = 2,[5] = 5}) --输出5
这个表里没有数组部分而存在散列桶部分时,也是针对其中键值为正整数的部分进行取长度操作。
print(#{[1] = 1,[2] = 2,1,2,3}) --输出3
而如果表中混合了两种风格的数据,那么优先取数组部分的长度。
优化
1.尽量不要将一个表混用数组和散列桶部分,即一个表最好之存放一类数据。Lua的实现上确实提供了两者统一表示的遍历,但是这不意味着使用着就应该会用着两种方式。
2.尽量避免进行重新散列操作,因为重新散列操作的代价极大。