lua 的整体效率是很高的,其中,它的 table 实现的很巧妙为这个效率贡献很大。

lua 的 table 充当了数组和映射表的双重功能,所以在实现时就考虑了这些,让 table 在做数组使用时尽量少效率惩罚。

lua 是这样做的。它把一个 table 分成数组段和 hash 段两个部分。数字 key 一般放在数组段中,没有初始化过的 key 值全部设置为 nil 。当数字 key 过于离散的时候,部分较大的数字 key 会被移到 hash段中去。这个分割线是以数组段的利用率不低于 50% 为准。 0 和 负数做 key 时是肯定放在 hash 段中的。

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

这种 table 的实现策略,首先保证的是查找效率。对于把 table 当数组使用时将和 C 数组一样高效。对于 hash 段的值,查找几乎就是计算 hash 值的过程(其中string 的 hash 值是事先计算好保存的),只有在碰撞的时候才会有少许的额外查找时间,而空间也不至于过于浪费。在 hash 表比较满时,插入较容易发生碰撞,这个时候,则需要在表中找到空的插槽。lua 在table 的结构中记录了一个指针顺次从一头向另一头循序插入来解决空槽的检索。每个槽点在记录 next 指针保存被碰撞的 key 的关联性。

整个来说,这种解决方法是非常不错的。

关于映射表的实现,我前段时间也做过一个别的研究。贴在留言本上:
<a href="http://www.codingnow.com/2004/board/view.php?paster=777&reply=0">树表结合的一种映射表实现</a>
<a href="http://www.codingnow.com/2004/board/view.php?paster=776&reply=0">在 vector , map , list 间取得平衡</a>

 

able 的构造器指的是创建 table 的表达式。每当对构造器进行求值,一个新的 table 就 被创建了。构造器可以创建一个空表或带有初始域的表。构造器的一般语法是:

tableconstructor ::= ‘{‘ [fieldlist] ’}’

fieldlist ::= field {fieldsep field} [fieldsep]
field ::= ‘[‘ exp ‘]’‘=’exp | exp | Name ‘=’exp | exp
fieldsep ::= ‘,’ | ‘;’

每一个形式如[exp1] = exp2 的域都会向新的表添加一个入口 ,它的键是 exp1,值是 exp2。
形式 name = exp 的域等同于形式[“name”] = exp 的域。最后,形式为 exp 的域等同于[i] = exp,
i 是从 1 开始的连续的整数,其它形式的域不会影响到 i 的计数。比如:

a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }

等同于

do
local t = {}
t[f(1)] = g
t[1] = "x"
t[2] = "y"
t.x = 1
t[3] = f(x)
t[30] = 23
t[4] = 45
a=t

end

-- 1st exp
-- 2nd exp

-- t["x"] = 1
-- 3rd exp

-- 4th exp

如果表中最后一个域的形式是一个函数调用表达式或者是一个变参表达式 ,那么这个表
达式返回的所有值都会紧接着前面的域而进入到表中(参考 3.4.9)。

在域列表的最后可以添加一个可选的分隔符,这样做是为了方便代码的机器生成

 

长度操作符为一元操作符 #。字符串的长度是它的字节数(即当每个字符是一个字节时 的传统长度含义 )。

程序可以通过__len 元方法(参考 2.4)去修改除了字符串外的其它数值求长度操作的行 为。

除非定义了__len 元方法,否则只有当表是一个顺序表时它的长度才能明确 ,也就是说, 表的正整数键值是{1..n},这种情况下,n 就是表的长度。如果一个表为

{10, 20, nil, 40}
这样的表不是一个顺序表 ,因为键 4 有值但键 3 没有值。(这个表没有像{1..n}这样的正

整数键值。)注意,非数字类型的键不会影响到一个表是否是一个顺序表。

 

在Lua 5.1中,长度操作符“#”用于返回一个数组或线性表的最后一个索引值。在实际项目中,我们经常使用该操作符来获取数组或线性表的长度。但是使用该操作符是存在陷阱的,比如下面一段代码:

  1. local a = {}
  2. a[1000] = 1
  3. print(#a)

这该输出多少呢?
在Lua中,对于所有未初始化的元素的索引结果都是nil。Lua将nil作为界定数组结尾的标志。当一个数组有“空隙”时,即中间含有nil时,长度操作符会认为这些nil元素就是结尾标记。因为a[1] = nil,所以,对于上述代码的输出应该是0。所以,在处理table的时候,需要考虑这个问题。那么对于含有nil的table,如何获取它的长度呢?我们可以使用table.maxn,它将返回一个table的最大正索引数,如下所示:

  1. local a = {}
  2. a[1000] = 1
  3. print(table.maxn(a)) -->1000

在Lua中,table既不是“值”,也不是“变量”,而是对象。可以将table想象成一种动态分配的对象,程序中仅仅有一个队它们的引用(指针)。table的创建是通过“构造表达式”完成的,最简单的构造表达式就是{}。
table永远是匿名的,一个引用table的变量与table自身之间没有固定的关联性,例如以下代码:

  1. local a = {} -- 创建一个table,并将它的引用存储在a
  2. a["x"] = 10
  3. local b = a -- ba引用同一个table
  4. print(b["x"])
  5. b["x"] = 20
  6. print(a["x"])
  7. b = nil -- 现在只有a还在引用table
  8. -- 错误:print(b["x"])
  9. print(a["x"])
  10. a = nil -- 现在不存在对table的引用

lua 的 table 处理的更多相关文章

  1. 打印Lua的Table对象

    小伙伴们再也不用为打印lua的Table对象而苦恼了, 本人曾也苦恼过,哈哈 不过今天刚完成了这个东西, 以前在网上搜过打印table的脚本,但是都感觉很不理想,于是,自己造轮子了~ 打印的效果,自己 ...

  2. lua的table表处理 及注意事项

    lua,一款很轻量级很nice很强大的脚本语言,做为lua中使用最为频繁的table表,在使用之时还是有颇多的好处与坑的: 下面是大牛 云风的一片关于lua table的blog,可使得对lua ta ...

  3. lua weak table 概念解析

    lua weak table 经常看到lua表中有 weak table的用法, 例如: weak_table = setmetatable({}, {__mode="v"}) 官 ...

  4. lua中 table 元表中元方法的重构实现

    转载请标明出处http://www.cnblogs.com/zblade/ lua作为游戏的热更新首选的脚本,其优势不再过多的赘述.今天,我主要写一下如何重写lua中的元方法,通过自己的重写来实现对l ...

  5. Linux下C/C++和lua交互-Table

    本来这些文章都是在我的个人网站www.zhangyi.studio,目前处在备案状态,暂时访问不了,所以搬到这边.  最近这两天需要弄清楚C++和lua间相互调用和数据传递,废话不多说,直接上过程. ...

  6. lua中 table 重构index/pairs元方法优化table内存占用

    转载请标明出处http://www.cnblogs.com/zblade/ lua作为游戏的热更新首选的脚本,其优势不再过多的赘述.今天,我主要写一下如何重写lua中的元方法,通过自己的重写来实现对l ...

  7. lua中table的遍历,以及删除

    Lua 内table遍历 在lua中有4种方式遍历一个table,当然,从本质上来说其实都一样,只是形式不同,这四种方式分别是: 1. ipairs for index, value in ipair ...

  8. C调用lua的table里面的函数

    网上搜索C.C++调用lua函数,有一大堆复制粘贴的. 但是搜索<C调用lua的table里面的函数> 怎么就没几个呢? 经过探索,发现其实逻辑是这样的: 1.根据name获取table ...

  9. C++对Lua中table进行读取、修改和创建

    C++代码: // LuaAndC.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #i ...

随机推荐

  1. Easyui入门视频教程 第04集---Easyui布局

    目录 目录 ----------------------- Easyui入门视频教程 第09集---登录完善 图标自定义   Easyui入门视频教程 第08集---登录实现 ajax button的 ...

  2. ios中创建自己的框架

    如果你是IOS的新手,并有.net开发的背景(就像我一样),你可能到处去找,哪里有dll呢? 其实,IOS平台是使用框架而不是dll,框架里面包含公共头文件和二进制文件.很不幸,XCode并不支持你自 ...

  3. Xcode全局替换内容,一键Replace

    有时需要在整个项目里,全局修改某一段话或文字,可以这样快速实现: 1.打开查找功能 2.输入你要替换的内容 比如,我这边想全局修改作者名称 3.点击Find,会出现一个框,会有replace出来,就和 ...

  4. SqlServer安装时的选项说明

    转自:https://blog.csdn.net/m0_37154839/article/details/80233446 看看组件的功能说明吧 服务器组件 说明 SQL Server 数据库引擎 S ...

  5. windows 7 提示缺少D3DCOMPILER_47.dll的正确解决方法

    下载 KB4019990补丁 我上传一下吧. 点击下载

  6. linux下yum命令出现Loaded plugins: fastestmirror Determining fastest mirrors

    今天yum install的时候出问题了,找了半天才找到一个可行的解决办法 fastestmirror是yum的一个加速插件,这里是插件提示信息是插件不能用了. 不能用就先别用呗,禁用掉,先yum了再 ...

  7. 保证java的jar包在后台运行

    nohup  java -jar XX.jar >temp.text &

  8. openstack neutron 深入

    一.概述 环境说明:

  9. 【HTML】WWW简介

    www 什么是WWW www(world wide web),又称为万维网,或通常称为web,是一个基于超文本方式的信息检索服务工具. WWW的工作模式 C/S结构(client/server结构), ...

  10. 2014百度之星第一题Energy Conversion

    Energy Conversion Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...