You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TJSONObject查找效率如何?大JSON场景下能否优化?

TJSONObject.GetValue/TryGetValue 性能与优化方案

1. 默认实现的效率与遍历行为

Delphi原生的TJSONObject内部通过TList<TJSONPair>存储键值对,调用GetValue或TryGetValue时,默认采用线性遍历逻辑:

  • 若目标键存在,遍历到匹配的TJSONPair后立即停止;
  • 若目标键不存在,会遍历完所有条目才返回查找失败的结果。

当JSON包含数千条条目时,单次查找的时间复杂度为O(n)。如果频繁执行查找操作(比如循环内多次调用),性能会随条目数量线性下降,耗时会明显增加。

2. 无额外依赖的优化方案

可以通过继承TJSONObject并扩展哈希表缓存的方式优化查找速度,核心思路是在子类内部维护一个TDictionary<string, TJSONValue>,将键与对应的值做映射,把查找复杂度降到O(1)。具体实现要点:

  • 继承TJSONObject,新增私有字段FKeyMap: TDictionary<string, TJSONValue>用于缓存键值映射;
  • 在构造函数中初始化字典,析构函数中释放资源;
  • 重写GetValue、TryGetValue方法,优先从字典中查找,找不到再走原生逻辑并同步字典;
  • 覆盖AddPair、RemovePair、Clear等修改键值对的方法,保证字典与原列表的数据同步(添加时插入字典,删除时移除对应条目);
  • 如需兼容键的大小写,可以在插入字典时统一转换为小写/大写存储。

简化示例代码

type
  THashedJSONObject = class(TJSONObject)
  private
    FKeyMap: TDictionary<string, TJSONValue>;
    procedure SyncKeyMap;
  public
    constructor Create; override;
    destructor Destroy; override;
    function GetValue(const Name: string): TJSONValue; override;
    function TryGetValue(const Name: string; out Value: TJSONValue): Boolean; override;
    function AddPair(const Pair: TJSONPair): TJSONObject; override;
    function RemovePair(const Name: string): TJSONPair; override;
    procedure Clear; override;
  end;

constructor THashedJSONObject.Create;
begin
  inherited;
  FKeyMap := TDictionary<string, TJSONValue>.Create;
  SyncKeyMap;
end;

destructor THashedJSONObject.Destroy;
begin
  FKeyMap.Free;
  inherited;
end;

procedure THashedJSONObject.SyncKeyMap;
var
  Pair: TJSONPair;
begin
  FKeyMap.Clear;
  for Pair in Pairs do
    FKeyMap.AddOrSetValue(Pair.JsonString.Value, Pair.JsonValue);
end;

function THashedJSONObject.GetValue(const Name: string): TJSONValue;
begin
  if FKeyMap.TryGetValue(Name, Result) then
    Exit;
  Result := inherited GetValue(Name);
  if Assigned(Result) then
    FKeyMap.AddOrSetValue(Name, Result);
end;

function THashedJSONObject.TryGetValue(const Name: string; out Value: TJSONValue): Boolean;
begin
  Result := FKeyMap.TryGetValue(Name, Value);
  if not Result then
  begin
    Result := inherited TryGetValue(Name, Value);
    if Result then
      FKeyMap.AddOrSetValue(Name, Value);
  end;
end;

function THashedJSONObject.AddPair(const Pair: TJSONPair): TJSONObject;
begin
  Result := inherited AddPair(Pair);
  if Assigned(Pair) then
    FKeyMap.AddOrSetValue(Pair.JsonString.Value, Pair.JsonValue);
end;

function THashedJSONObject.RemovePair(const Name: string): TJSONPair;
begin
  Result := inherited RemovePair(Name);
  if Assigned(Result) then
    FKeyMap.Remove(Name);
end;

procedure THashedJSONObject.Clear;
begin
  inherited;
  FKeyMap.Clear;
end;

注意事项

  • 若JSON对象会被频繁修改,必须确保所有修改操作都同步更新哈希表,否则会出现数据不一致的问题;
  • 原生TJSONObject的Pairs列表是有序的,哈希表不保证顺序,若需保留顺序可以结合TOrderedDictionary(Delphi XE7及以上版本支持)。

内容的提问来源于stack exchange,提问作者Peter Jones

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 02:26:09