Lua 的表是哈希表:键经哈希函数映射到槽位,两个键落进同一槽位就是冲突。解决冲突的两大流派:链地址法(Lua 表内部采用,冲突键挂链)与开放寻址(冲突后按探测序列找下一个空槽)。开放寻址省掉链表指针、内存紧凑,但删除麻烦——不能直接置 nil,要留墓碑标记堵住探测链;装载率过高时探测次数激增——理解这条性能悬崖,才能理解表操作"为什么突然变慢"。
线性探测的写入与读取。示例代码如下:
local CAP = 16
local slots = {}
local function hashKey(key)
local sum = 0
for i = 1, #key do
sum = sum + string.byte(key, i)
end
return sum % CAP + 1
end
local function put(key, value)
local idx = hashKey(key)
while slots[idx] and slots[idx].key ~= key do
idx = idx % CAP + 1
end
slots[idx] = { key = key, value = value }
end
local function get(key)
local idx = hashKey(key)
while slots[idx] do
if slots[idx].key == key then
return slots[idx].value
end
idx = idx % CAP + 1
end
return nil
end
物品索引接线。示例代码如下:
put("裁决之杖", 5000)
put("祖玛头像", 800)
print(get("裁决之杖"), get("不存在"))
两件物品哈希到不同槽各归其位;撞槽时线性探测顺延到下一个空位,读取沿同一路径回放。
装载率 50% 时线性探测平均约 1.5 次、查询微秒级;装载率冲到 90% 时平均探测超过 5.5 次——性能悬崖由装载率决定,扩容阈值惯例定在 70%。对比链地址法:开放寻址无指针跳转,单次查询快约 30%,代价是删除需要墓碑、扩容必须全量重哈希。
三个不适用场景:一是删除频繁的场景——墓碑堆积让探测链越来越长,链地址摘链更干净;二是日常业务直接用 Lua 原生表即可(冲突已由虚拟机处理),手写开放寻址的价值在教学理解与特殊键约束;三是键分布极度集中(哈希值扎堆),探测序列被拉长,先改哈希函数再谈其他。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏】 一、一行代码拆解:hp = 10000 + teamN 5000 —— 运镖劫镖的全部骨架:镖车按护送人数增强血量…
【语法】 一、隐蔽陷阱:逐个插入建堆要 n 次上浮;自底向上从末个非叶子节点倒序下沉,一遍线性把乱序表调成合法堆。 二、底层…
【语法】 一、抛坑提问:一个数等于它全部真因子之和就叫真因子和数,6 等于 1 加 2 加 3——判定只需枚举到平方根配对求…
【游戏】 一、一行代码拆解:n = math.floor(have / 5) —— 批量合成的全部骨架:5 个碎片合成 1 …
【游戏】 一、一行代码拆解:if INSURED[actor] then 赔付 end —— 装备保险的全部骨架:死亡掉落判…
【语法】 一、隐蔽陷阱:找第 K 小元素先全量排序再取下标,n log n 浪费在无关排序上;快速选择借用快排分区——每轮只…