lua如何处理表的增长?
它是否等同于Java中的ArrayList
?即需要连续内存空间的内存空间,并且当它比已经分配的空间大时,内部数组被复制到另一个内存空间。
有一种聪明的方式可以带领吗?
我的问题是,如何将表存储在内存中?我不是问如何在Lua中实现数组。
答案 0 :(得分:5)
(假设您指的是Lua的最新版本;描述5.3的行为(对于5.0-5.2应该是(几乎?)相同。)
在引擎盖下,表包含一个数组和一个哈希部分。两者(独立地)以两个幂的步长增长和缩小,如果不需要则两者都可以不存在。
大多数键值对将存储在哈希部分中。但是,所有正整数键(从1开始)都是存储在数组部分中的候选。数组部分仅存储值而不存储键(因为它们等同于元素在数组中的位置)。允许最多一半的已分配空间为空(即包含nil
s - 作为间隙或尾随空闲插槽)。 (将留下过多空插槽的数组候选将被放入散列部分。如果数组部分已满,但散列部分中有剩余空间,则任何条目都将转到散列部分。)
对于数组和散列部分,插入可以触发调整大小,如果先前已经删除了足够多的条目,则可以触发下一个更大的2的幂,或者更低到2的任何更小的幂。 (实际上触发向下调整大小是非平凡的:rehash
是调整表的唯一位置(并且两个部分同时调整大小),并且只从luaH_newkey
调用< em> if 1 这两个部分中没有足够的空间。)
有关详细信息,请查看The Implementation of Lua 5.0的第4章,或检查来源:基本上所有相关内容都发生在ltable.c
中,有趣的阅读起点是rehash
(in ltable.c
)(调整大小函数),主解释器循环luaV_execute
(in lvm.c
)或更具体地luaV_settable
(also there)(在表中存储键值对时会发生什么)。
1 例如,为了缩小包含大型数组部分且没有散列的表,您必须清除所有数组条目,然后在散列部分(即使用非整数键,值可以是任何包括 nil
),最终得到一个不包含数组部分和1元素散列部分的表。
如果两个部分都包含条目,则必须首先清除哈希部分,然后向数组部分添加足够的条目以填充数组和哈希组合(以触发调整大小,这将留下具有大数组部分的表,并且没有哈希),然后清除上面的数组。 2 (首先清除数组然后哈希将不起作用,因为在清除这两个部分后你将没有数组和一个巨大的哈希部分,并且你不能触发调整大小,因为任何条目都会转到哈希。)
2 实际上,很多更容易丢掉桌子并制作新桌子。为确保表格缩小,您需要知道实际分配的容量(不是当前的条目数,以及Lua不会告诉您的,至少不会直接告诉您) ,然后得到所有步骤和所有大小恰到好处 - 混合步骤的顺序或无法触发调整大小,你最终会得到一个巨大的表,如果你把它作为一个数组使用它甚至可能会执行得更慢...(存储在散列中的数组候选者也存储其密钥,例如缓存行中有用数据量的一半。)
答案 1 :(得分:1)
从Lua 5.0开始,表是哈希表和数组的混合体。来自The Implementation of Lua 5.0:
用于优化用作数组的表的新算法:
与其他脚本语言不同, Lua不提供数组类型。相反,Lua程序员使用 带有整数索引的常规表来实现数组。 Lua 5.0使用了一个新的 检测表是否被自动用作数组的算法 存储与实际数组中的数字索引关联的值, 而不是将它们添加到哈希表。该算法在中讨论 第4节。
以前的版本只有哈希表。