学Lua你必须要清楚的要点之 Table

简介

Lua程序设计(第4版):
表(Table)是Lua语言中最主要(实际上也是唯一的)和强大的数据结构。使用表,Lua语言可以以一种简单、统一且高效的方式表示数组、集合、记录和其他很多数据结构。

可以理解成 万物皆可为表

Table基本使用

构造器 {}

t = {}  -- 创建一个表并将表的引用赋值给t
t1 = {"Hello","World"} -- 创建一个数字索引的表,含有两个元素 
t1[1] -- "Hello"
t["a"] = 1 -- 增加一个 键为“a” 值为 1的新元素
t["b"] = "Hello" -- 增加一个 键为“b” 值为 "Hello"的新元素 
t["a"]  -- 1

数组
Lua语言提供了获取序列长度的操作符 #。

a = {1,2,3,4,5}
#a  -- 5

但对于中间存在nil的表而言,序列长度操作是不可靠的

遍历表

-- pairs 遍历受限于Lua低层实现机制,遍历顺序是随机的
for k,v in pairs(t) do
	...
end
--对于数组列表来言可以使用 ipairs ,这会确保顺序
for k,v in ipairs(array) do
	...
end

安全访问 ?.
lua5.3 支持

t = t1?.a?.b -- 使用?.时当表为nil时会产生结果nil而不会报错

Table 的实现

在我们日常使用Lua语言时,你会发现 table 主要的作用是充当数组或是映射表的功能,为了实现这两个功能并且使它高效,Lua是这样做的:

  • 它把一个 table 分成数组段Hash段两个部分。
  • 数字key 一般放在数组段中,没有初始化过的 key 值全部设置为 nil
  • 当数字 key 过于离散的时候,部分较大的数字 key 会被移到 Hash段中去。这个分割线是以数组段的利用率不低于 50% 为准。
  • 0 和 负数做 key 时放在 Hash 段中的。
  • stringnumber 都放在一起做 Hash ,分别有各自的算法,但是 Hash 的结果都在一个数值段中。

Hash 段采用闭散列方法,即,所有的值都存在于表中。如果Hash 发生碰撞,额外的数据记在空闲槽位里,而不额外分配空间存放。当整个个表放满后,Hash 段会扩大,所有段内的数据将被重新 Hash ,重新 Hash 后,冲突将大大减少。

lua的hash表的hash算法比较特别,一般的hash表都是根据key算出hash(key),然后把这个key放在hash表的hash(key)位置上,如果有冲突的话,就放在hash(key)位置的链表上。
但是lua的hash表中,如果有冲突的话,lua会找hash表中一个空的位置(从后往前找,假设为x),然后把新的key放在这个空的位置x上,并且让hash表中hash(key)处的节点的nk.next指向x。这个意思就是,假如有冲突的话,不用重新分配空间来存储冲突的key,而是利用hash表上未用过的空格来存储。但是这样会引入另外一个问题,本来key是不应该放在x的,假设有另外一个key2,hash(key2)算出来的位置也在x的话,那就表示本来x这个位置应该是给key2的,但是由于x被key占用了,导致key2没地方放了。这时候lua的处理方式是把key放到另外一个空格,然后让key2占回x。当hash表已经没有空格的时候,lua就会resize这个hash表。这样做的好处主要是不用动态申请内存空间,hash表初始化的时候有多少内存空间就用多少,不够就resize这个hash表。

rehash和esize过程

在这里插入图片描述
加入key需要重新分配hash与array的空间
先重新计算出需要分配的空间
接着创建新的hash表和重新分配数组空间,然后从后到前遍历将老的hash表中值搬到新表中
最后释放掉老的hash表

元表

学Lua你必须要清楚的要点之 元表与面向对象

弱引用 weaktable

Lua 弱引用Table(weak table)

Table总结

(1)在对table操作时,尽量不要触发rehash操作,因为这个开销是非常大的。在对table插入新的键值对时(也就是说key原来不在table中),可能会触发rehash操作,而直接修改已存在key对于的值,不会触发rehash操作的,包括赋值为nil。

(2)在遍历一个table时,不允许向table插入一个新键,否则将无法预测后续的遍历行为,但lua允许在遍历过程中,修改table中已存在的键对应的值,包括修改后的值为nil,也是允许的。

(3)table中要想删除一个元素等同于向对应key赋值为nil,等待垃圾回收。但是删除table一个元素时候,并不会触发表重构行为,即不会触发rehash操作。

原创文章 28 获赞 30 访问量 2428

猜你喜欢

转载自blog.csdn.net/qq_28820675/article/details/105523376