本文来自《Lua设计与实现》的阅读笔记,推荐Lua学习者可以购买一本,深入浅出讲解lua的设计和实现原理,很赞,哈哈
 
Lua中对于表的设计,是基于数组和散列表,和其他语言不同,对于数组的下标是从1开始的,对于散列表而言,只要其键值补位nil,都可以存储在其中。
 
一、table的基本类型定义
首先看看table的数据定义,参考源码lobject.h
CommonHeader, 参看专栏前面的文章;
flags 这是一个lua的byte类型的数据,用于表示表中提供了哪些元方法,比如是否提供了元方法_index,该数据最开始设置为1,如果进行查找一次,比如_index,如果存在,这该元方法对应的flag bit设置为0,在下一次查找的时候,只需要比较这个bit即可,对应的元方法在ltm.h中
lsizenode,为散列表的大小,必定为2的幂对应的数字;
metatable,该table的元表;
array,该table的数组的指针
node, 该table的散列表的起始位置的指针;
lastfree, 该散列表的最后位置的指针
gclist, gc相关的链表
sizearray, 数组的大小,不一定为2的幂对应的数字
对于node数据,类似于其他语言中的字典设计\hash设计,就是一个键值对集合,其定义为:
需要提一下的是对于key的设计采用的是union,也就是说Lua的散列表的key,可以为nk对应的struct,也可以是TValue类型
 
二、table相关的操作的实现原理
1、查找算法的实现原理
借用原文的伪代码:
if 输入的key为整数 && key >= 0 && key <= 数组的大小
尝试在数组部分查找
else 在散列表部分查找
计算出该key的散列值,据其查找对应的node所在散列表中的位置,然后遍历其对应的链表,查找是否有该key对应的元素
举例:
local t = {}
t[1] = 0
t[100] = 0
那么1是在数组中查找,100就是在散列表中去查找了(100大于数组的len)
 
2、新增元素的实现原理
给lua中添加新元素的时候,会有可能触发重新分配table中的数组和散列表,其本质来自于散列表的rehash(由于lua对于下标超过数组的大小的数字,都会存储在散列表部分去,所以数组部分的插值不会触发rehash)
散列表的组织,就是多个mainposition,每个单独的mainposition会对应一个数据链表,当插入一个key的时候,会调用luaHset\luaH_setnum\luaH_setstr,来获得该key对应的TValue指针,如果没有,则调用内部的newkey函数来分配一个新的key:
基本的实现过程看源代码写的比较详细,这儿说一下rehash部分的操作,在ltable.c中:
1) nums中存放的是元素的数量
2)分表遍历数组(numusearray)和散列表(numusehash),统计更新nums中的数量大小
3) 重新计算数组和hash部分的大小,数组大小的计算规则:逐个遍历nums数组,获得其范围区间内所包含的整数数量大于50%的最大索引,作为rehash后的数组大小,这个索引值来自与computesizes函数:
可能看了会有点迷糊,那我就用大白话说一下吧:
首先nums数组在统计后,每个下标对应的是处于当前2^(i -1) - 2^i中的元素的个数,然后不断的累加计算,求得满足 sum > 2^n/2的最大下标值(这个下标值是nums数组中的)
所以,在不同的rehash阶段,table中的同一个key可能会在数组部分和散列表部分交替出现,也是可能的。
由于rehash会带来较大的性能消耗,所以一般都尽量避免,比如在创建表的时候,就采用预填充的算法
 
3、取长度算法的原理
如果table中元表没有重载len方法,则调用的是luaH_getn方法,其基本的伪代码为:
if 表中存在数组部分:
初始化i = 0, j = sizearray
  while(j - i > 1){
    m = (j + i)/2
  if(array[m-1] == nil)
    j = m
  else
    i = m
  }
  return i
else
  查找表中散列表长度,算法同数组部分
对于表中只有散列表的时候,其实质就是对键值为正整数的部分进行长度操作,如果既有数组,又有散列表,则优先对数组部分进行长度操作

Lua中table的实现-《Lua设计与实现》的更多相关文章

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

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

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

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

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

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

  4. lua中 table.getn(t) 、#t、 table.maxn(t) 这三个什么区别?

    lua中 table.getn(t) .#t. table.maxn(t) 这三个什么区别? RTlocal t = {1,888,x= 999,b=2,5,nil,6,7,[10]=1,8,{z = ...

  5. lua中table如何安全移除元素

    在Lua中,table如何安全的移除元素这点挺重要,因为如果不小心,会没有正确的移除,造成内存泄漏. 引子 比如有些朋友常常这么做,大家看有啥问题 将test表中的偶数移除掉local test = ...

  6. lua中table的常用方法

    转载:https://blog.csdn.net/Fenglele_Fans/article/details/83627021 1:table.sort() language = {"lua ...

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

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

  8. Lua中Table的学习

    --table 是 Lua 的一种数据结构,用来帮助我们创建不同的数据类型,如:数组.字典等 --Lua也是通过table来解决模块(module).包(package)和对象(Object)的. 例 ...

  9. lua中遍历table的几种方式比较

    当我在工作中使用lua进行开发时,发现在lua中有4种方式遍历一个table,当然,从本质上来说其实都一样,只是形式不同,这四种方式分别是: for key, value in pairs(tbtes ...

随机推荐

  1. Redis --> Redis架构设计

    Redis架构设计 一.前言   Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. 它支持多种类型的数据结构,如 字符串(strings), 散列 ...

  2. Java多线程:死锁

    周末看到一个用jstack查看死锁的例子.昨天晚上总结了一下jstack(查看线程).jmap(查看内存)和jstat(性能分析)命令.供大家参考  1.Jstack 1.1 jstack能得到运行j ...

  3. Python 自学 之 String 常见操作

    这是在Python 3.5.3版本下测试的.# Author Taylor_Manitoname ="my name is alex"#capitalized 大写的print(& ...

  4. C#/AutoCAD 2018/ObjectArx/二次开发再说实体(六)

    这些函数对大家很有用,如果想获取详细源代码请加云幽学院yunyou.ke.qq.com报名免费课程,如果想学习更系统.更全面的知识请报名收费课程,有大量开发案例共享. 1.获取模型空间中所有实体 #r ...

  5. js中的类型转换

    先介绍一下 typeof 的使用方法: typeof(mix)   或者  typeof  mix 其中 mix 可以是任何数据类型 typeof 的返回值有六种:number.string.bool ...

  6. 听翁恺老师mooc笔记(1)--为何选择学习C

    知识点1:众多编程语言,为何选择C? 现在我们的同学喜欢java,也参加很多java的培训班,java是比较热门,但是C语言在工业界依然有重要的地位,在很多领域无可替代,几乎所有和硬件打交道的地方都得 ...

  7. docopt——好用的Python命令行参数解释器

    Qingchat使用的命令行参数解释器是 docopt,用下来感觉非常棒,所以决定介绍一下这个库.( 奉劝各位看官,真爱生命,远离argparse. ) 介绍 docopt 本质上是在 Python ...

  8. 09-移动端开发教程-Sass入门

    1. 引言 CSS3之前的CSS都大都是枚举属性样式,而编程语言强大的变量.函数.循环.分支等功能基本都不能在CSS中使用,让CSS的编程黯淡无光,Sass就是一种增强CSS编程的扩展语言(CSS4也 ...

  9. selenium多个标签页的切换(弹出新页面的切换)

    1_windows = driver.current_window_handle #定位当前页面句柄 all_handles = driver.window_handles #获取全部页面句柄 for ...

  10. C#之Socket通信

    0.虽然之前在项目中也有用过Socket,但始终不是自己搭建的,所以对Server,Clinet端以及心跳,断线重连总没有很深入的理解,现在自己搭建了一遍加深一下理解. 服务端使用WPF界面,客户端使 ...