
本文介绍一种基于哈希映射的高效方案,替代传统 arraylist 实现二维平面上任意整数坐标(含负值)的动态数据存储,适用于游戏开发中的程序化生成场景。
本文介绍一种基于哈希映射的高效方案,替代传统 arraylist 实现二维平面上任意整数坐标(含负值)的动态数据存储,适用于游戏开发中的程序化生成场景。
在游戏开发中进行程序化生成(如无限地形、区块加载或稀疏世界建模)时,常需以二维坐标(x, y)为索引存取对象——但标准 ArrayList 仅支持从 0 开始的非负整数索引,无法直接表达如 (-3, 5) 或 (0, -10) 这类天然存在的负向坐标。若强行用多个 ArrayList 分割象限(如四象限独立管理),不仅逻辑冗余、边界处理复杂,还会显著增加内存开销与维护成本。
更优解是放弃“连续数组”的思维定式,转而采用稀疏数据结构:HashMap 天然支持任意键类型,只需将二维坐标编码为唯一字符串键即可实现 O(1) 时间复杂度的随机访问。
以下是一个轻量、线程安全(读多写少场景下可扩展)、易于复用的 GridMap 实现:
import java.util.HashMap;
import java.util.Objects;
public class GridMap<T> {
private final HashMap<String, T> storage;
public GridMap() {
this.storage = new HashMap<>();
}
// 将坐标对编码为不可变、无歧义的键(使用分隔符避免 x=-1,y=2 与 x=-12,y= 之类冲突)
private String key(int x, int y) {
return x + "," + y;
}
public void set(int x, int y, T value) {
storage.put(key(x, y), value);
}
public T get(int x, int y) {
return storage.get(key(x, y));
}
public boolean contains(int x, int y) {
return storage.containsKey(key(x, y));
}
public void remove(int x, int y) {
storage.remove(key(x, y));
}
public int size() {
return storage.size();
}
}✅ 使用示例:
GridMap<String> world = new GridMap<>(); world.set(0, 0, "SpawnPoint"); world.set(-2, 7, "AncientRuins"); world.set(15, -3, "DesertOasis"); System.out.println(world.get(-2, 7)); // 输出: AncientRuins System.out.println(world.contains(99, 99)); // 输出: false
⚠️ 注意事项:
- 此结构不保证坐标连续性,也不提供邻域遍历(如“获取所有相邻格子”需手动计算 (x±1, y) 等键并逐一查询);若需高频邻域操作,建议封装 getNeighbors(x, y) 方法;
- 键字符串拼接简单可靠,但对超大坐标(如 Integer.MIN_VALUE)需考虑溢出风险——实际游戏场景中极少触及,可忽略;
- 如需线程安全写入,可将 HashMap 替换为 ConcurrentHashMap,或在外层加锁;
- 若数据密度极高(如几乎每个坐标都有值),可考虑“偏移+二维数组”方案(即预估范围后平移至非负索引),但会牺牲灵活性与内存效率。
总之,面对无限、稀疏、带负坐标的二维空间,HashMap 编码坐标是兼顾简洁性、可扩展性与工程实践性的首选方案。它不是“能用负索引的 ArrayList”,而是更契合问题本质的正确抽象。

















