Delphi 哈希表?

15

我有一段Java代码,用于从文本文件中填充HashMap。
HashMap<String, String[]> data = new HashMap<String, String[]>();

我使用它来创建键值对。值是一个字符串数组。我必须遍历每个可能的键值对组合(因此还必须遍历String[]数组)。这在Java中可以实现,现在我需要将其移植到Delphi中。有可能吗?如何操作? 谢谢!


2
使用 Generics.Collections.TDictionary<TKey,TValue>。 - David Heffernan
3个回答

20
在 Delphi 2009 及更高版本中,您可以使用泛型集合 TDictionary<string, TStringlist>
在旧版本中,您可以使用 TStringlist,其中 TStringlist 中的每个项目都有一个关联的对象值,类型为 TStrings。
Docwiki 有一个页面可以开始使用 TDictionary

哦,谢谢。这看起来不错。这个有迭代器吗?在Java中,我使用递归方法来获取每个键值对的组合(注意:在Delphi上下文中,值是一个字符串列表...) - someuser
你可以使用 for in 来枚举键值对。 - David Heffernan
我的代码看起来很像这个(在stackoverflow上找到的):http://stackoverflow.com/questions/5322948/recursive-iterate-hashmap。这在Delphi中如何翻译? - someuser
@someuser:看一下我的补充,或许可以帮助你入门。 - mjn

4
如果您使用较旧版本的Delphi(Delphi 6及以上),您也可以使用动态数组记录,然后使用我们的TDynArrayTDynArrayHashed包装器创建一个只有一个字段的动态数组记录字典。请参见此单元TDynArrayHashed包装器是为了速度而开发的。
下面是一些示例代码(来自提供的单元测试):
var ACities: TDynArrayHashed;
    Cities: TCityDynArray;
    CitiesCount: integer;
    City: TCity;
    added: boolean;
    N: string;
    i,j: integer;
const CITIES_MAX=200000;
begin
  // valide generic-like features
  // see http://docwiki.embarcadero.com/CodeExamples/en/Generics_Collections_TDictionary_(Delphi)
  ACities.Init(TypeInfo(TCityDynArray),Cities,nil,nil,nil,@CitiesCount);
  (...)
  Check(ACities.FindHashed(City)>=0);
  for i := 1 to 2000 do begin
    City.Name := IntToStr(i);
    City.Latitude := i*3.14;
    City.Longitude := i*6.13;
    Check(ACities.FindHashedAndUpdate(City,true)=i+2,'multiple ReHash');
    Check(ACities.FindHashed(City)=i+2);
  end;
  ACities.Capacity := CITIES_MAX+3; // make it as fast as possible
  for i := 2001 to CITIES_MAX do begin
    City.Name := IntToStr(i);
    City.Latitude := i*3.14;
    City.Longitude := i*6.13;
    Check(ACities.FindHashedAndUpdate(City,true)=i+2,'use Capacity: no ReHash');
    Check(ACities.FindHashed(City.Name)=i+2);
  end;
  for i := 1 to CITIES_MAX do begin
    N := IntToStr(i);
    j := ACities.FindHashed(N);
    Check(j=i+2,'hashing with string not City.Name');
    Check(Cities[j].Name=N);
    CheckSame(Cities[j].Latitude,i*3.14);
    CheckSame(Cities[j].Longitude,i*6.13);
  end;
end;

所以针对您的问题:
type
  TMyMap = record
    Key: string;
    Value: array of string;
  end;
  TMyMapDynArray = array of TMyMap;

var
  Map: TMyMap;
  Maps: TMyMapDynArray;
  MapW: TDynArrayHashed;
  key: string;
  i: integer;
begin
  MapW.Init(TypeInfo(TMyMapDynArray),Maps);
  Map.Key := 'Some key';
  SetLength(Map.Value,2);
  Map.Value[0] := 'One';
  Map.Value[1] := 'Two';
  MapW.FindHashedAndUpdate(Map,true); // ,true for adding the Map content
  key := 'Some key';
  i := MapW.FindHashed(key);
  // now i=0 and Maps[i].Key=key
  for i := 0 to MapW.Count-1 do // or  for i := 0 to high(Maps) do
    with Maps[i] do
    // now you're enumerating all key/value pairs
end;

1
我刚刚使用了这个包装器来读取我的.map文件,它的效果非常好。速度非常快,易于使用。.map文件可以在瞬间读取,并且符号名称会使用快速哈希添加到内部列表中。请参见此链接 - Arnaud Bouchez

4

自Delphi 6以来,预定义的容器类集合中包括TBucketList和TObjectBucketList。这两个列表是关联的,意味着它们有一个键和一个实际条目。键用于标识项目并搜索它们。要添加项目,您需要使用Add方法,并提供两个参数:键和数据。当您使用Find方法时,您需要传递键并检索数据。通过使用Data数组属性并将键作为参数传递,也可以实现相同的效果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接