PHP无原生稀疏表,需用关联数组模拟:键任意、未设键不占内存;用array_key_exists判断存在性,foreach遍历仅真实项;范围查询需额外排序或外部存储。

稀疏表在 PHP 中没有原生支持
PHP 本身不提供「稀疏表」(sparse table)这种数据结构——它不是像 array 或 SplFixedArray 那样的内置类型。所谓“稀疏表”,通常指逻辑上大范围索引(如 0–10⁶)、但实际只存储少量非空值的结构。你在 PHP 中实现它,本质是用普通数组或对象模拟,关键在于**避免预分配内存**、**按需存取**、**跳过空槽**。
用关联数组模拟稀疏表最常用
PHP 的 array 是哈希表实现,天然适合稀疏场景:键可以是任意整数(包括很大或负数),未设置的键不占内存。这是绝大多数 PHP 稀疏需求的实际解法。
- 直接用
$table[1234567] = 'value'赋值,不初始化整个范围 - 检查是否存在用
isset($table[$key])或array_key_exists($key, $table)(注意二者对null处理不同) - 遍历时用
foreach ($table as $index => $value),只迭代真实存在的项 - 不要用
range(0, 999999)+array_fill初始化,那会立刻吃光内存
$sparse = []; $sparse[0] = 'start'; $sparse[1000000] = 'end'; // 中间 999998 个索引根本不存在 var_dump(count($sparse)); // int(2) var_dump(isset($sparse[500000])); // bool(false)
需要范围查询时考虑 SortedList 或自定义类
纯关联数组不支持快速查找「小于等于某 key 的最大已存键」或「下一个非空位置」这类操作。若业务涉及区间扫描(比如时间戳稀疏日志、坐标格网),就得自己封装逻辑:
- 用
ksort()维护键有序(仅在写入后偶尔调用,避免每次插入都排序) - 用
array_keys($table)提取所有键,再用array_filter()或二分查找(array_search不适用,得手写)定位 - 若高频查询,可额外维护一个
SplMinHeap存键,或用Redis的ZSET做外部稀疏索引
警惕 array_key_exists 和 isset 的行为差异
这是最容易踩的坑:如果某个键被显式设为 null,isset($table[$key]) 返回 false,而 array_key_exists($key, $table) 返回 true。稀疏表中你往往关心“是否被赋值过”,而非“是否为非 null”——所以多数情况该用 array_key_exists。
立即学习“PHP免费学习笔记(深入)”;
-
$t[10] = null;→isset($t[10])是false,array_key_exists(10, $t)是true - 稀疏表中“存在但值为 null”和“完全不存在”语义不同,选错判断方式会导致漏数据或误判










