Skip to content

LinkedMap 使用文档

LinkedMap 是 Zeze 框架提供的持久化有序Map实现,结合了 HashMap 的快速查找双向链表的顺序访问 特性。所有操作都在事务中执行,数据会自动持久化到配置的数据库。

Zeze.Collections.LinkedMap<V extends Bean>
特性说明
有序性元素按插入顺序排列,支持移动到头部/尾部
持久化数据自动同步到数据库
事务安全所有操作在事务中执行,乐观锁保证并发安全
热更新支持支持值类型的动态重载
节点分块大数据量时分多个节点存储,提高性能

// 在应用启动时创建 Module
Zeze.Application zeze = new Zeze.Application(config);
LinkedMap.Module linkedMapModule = new LinkedMap.Module(zeze);
// 打开一个名为 "playerItems" 的 LinkedMap,值类型为 Item
LinkedMap<Item> itemMap = linkedMapModule.open("playerItems", Item.class);
// 指定节点大小(每个节点存储的元素数量,默认30)
LinkedMap<Item> itemMap = linkedMapModule.open("playerItems", Item.class, 50);
// 开启事务
zeze.newProcedure(() -> {
// 添加元素(默认添加到头部)
itemMap.put("item1", new Item());
// 添加到尾部
itemMap.put("item2", new Item(), false);
// 获取元素
Item item = itemMap.get("item1");
// 获取或创建
Item item = itemMap.getOrAdd("item3");
// 删除元素
Item removed = itemMap.remove("item1");
// 获取元素数量
long count = itemMap.size();
// 判断是否为空
boolean empty = itemMap.isEmpty();
return 0;
}, "example").call();

方法说明
open(String name, Class<T> valueClass)打开 LinkedMap,默认节点大小30
open(String name, Class<T> valueClass, int nodeSize)打开 LinkedMap,指定节点大小
openConcurrent(String name, Class<T> valueClass)打开并发版本 CHashMap
方法返回值说明
get(String id)V根据ID获取值
get(long id)V根据long类型ID获取值
put(String id, V value)V插入键值对(添加到头部),返回旧值
put(String id, V value, boolean ahead)V插入键值对,ahead=true添加到头部,false添加到尾部
getOrAdd(String id)V获取或创建值
remove(String id)V删除元素,返回被删除的值
方法返回值说明
moveAhead(String id)long将元素移动到链表头部
moveTail(String id)long将元素移动到链表尾部
方法返回值说明
size()long获取元素总数
isEmpty()boolean判断是否为空
getName()String获取 LinkedMap 名称
getRoot()BLinkedMap获取根节点信息
getNode(long nodeId)BLinkedMapNode根据节点ID获取节点
getFirstNode(OutLong nodeId)BLinkedMapNode获取第一个节点
getNodeById(String id)BLinkedMapNode根据元素ID获取所在节点
getNodeId(String id)Long获取元素所在的节点ID
方法说明
walk(TableWalkHandle<String, V> func)遍历所有元素,返回处理的元素数量
clear()清空所有元素(异步删除)
removeNode(long nodeId)删除整个节点及其所有元素

// 定义物品Bean
public class Item extends Bean {
public int itemId;
public int count;
// ...
}
// 使用
LinkedMap<Item> bag = linkedMapModule.open("player_bag_123", Item.class);
zeze.newProcedure(() -> {
// 添加物品到背包头部
Item sword = new Item();
sword.itemId = 1001;
sword.count = 1;
bag.put("slot_1", sword);
// 获取物品
Item item = bag.get("slot_1");
// 移动物品到背包末尾
bag.moveTail("slot_1");
return 0;
}, "bag_op").call();
long processed = linkedMap.walk((id, value) -> {
System.out.println("ID: " + id + ", Value: " + value);
return true; // 返回true继续遍历,false停止
});

示例3:使用 CHashMap(高并发场景)

Section titled “示例3:使用 CHashMap(高并发场景)”
// CHashMap 内部使用多个 LinkedMap 分片,提高并发性能
CHashMap<Item> concurrentMap = linkedMapModule.openConcurrent("shared_items", Item.class);
zeze.newProcedure(() -> {
concurrentMap.put("item_001", new Item());
return 0;
}, "concurrent_op").call();

BLinkedMap (根节点)
├── headNodeId // 头节点ID
├── tailNodeId // 尾节点ID
├── lastNodeId // 最后分配的节点ID
└── count // 元素总数
BLinkedMapNode (数据节点) - 双向链表
├── prevNodeId // 前驱节点
├── nextNodeId // 后继节点
└── values[] // 元素列表(每个节点最多 nodeSize 个元素)
BLinkedMapKey (索引) - 快速定位
└── name + id → nodeId
表名用途
_tLinkedMapsnameBLinkedMap存储根节点
_tLinkedMapNodesname + nodeIdBLinkedMapNode存储数据节点
_tValueIdToNodeIdname + idnodeId值ID到节点ID的映射

  1. 事务要求:所有操作必须在 Procedure 中执行
  2. 名称限制:名称不能包含 @ 字符(保留用于内部)
  3. 值类型:值类型必须继承自 Bean
  4. clear 操作clear() 使用延迟删除,不会立即删除所有节点
  5. 节点大小nodeSize 只影响新创建的节点,已有节点大小不变

ZezeJava/ZezeJava/src/main/java/Zeze/Collections/LinkedMap.java