Java 如何在ProtoBuf中高效地建模HashMap/Dictionary

Java 如何在ProtoBuf中高效地建模HashMap/Dictionary,java,serialization,protocol-buffers,protobuf-net,Java,Serialization,Protocol Buffers,Protobuf Net,我有一个由.NET代码序列化的protobuf文件,我想将它转换成Java。在.NET代码中,有字典数据类型,原型模式如下所示 message Pair { optional string key = 1; optional string value = 2; } message Dictionary { repeated Pair pairs = 1; } 正如stackoverflow post中所述 我可以使用proto将proto文件编译成Java类。我可以成功地

我有一个由.NET代码序列化的protobuf文件,我想将它转换成Java。在.NET代码中,有字典数据类型,原型模式如下所示

message Pair {
   optional string key = 1;
   optional string value = 2;
}

message Dictionary {
   repeated Pair pairs = 1;
}
正如stackoverflow post中所述

我可以使用proto将proto文件编译成Java类。我可以成功地将protobuf文件反序列化为Java对象。唯一的问题是,它转换为Java中成对对象的列表,而不是HashMap。当然,我仍然拥有所有数据,但是我无法像我所希望的那样高效地访问数据。如果我有键的值,我必须循环遍历整个列表以获得其相应的值。这似乎不是最优的

我想知道是否有更好的方法在protobuf中建模Dictionary/Map数据类型

谢谢

更新:

我尝试了Jon Skeet的建议,在addressbook示例中添加map type字段,但仍然遇到了问题

message Person {
  required string name = 1;
  required int32 id = 2;        // Unique ID number for this person.
  optional string email = 3;
  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }
  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }
  repeated PhoneNumber phone = 4;
  map<string, string> mapdata = 5;
}
根据GoogleProtobuf文档,Proto2确实支持地图类型。正如我引述的

映射不能重复、可选或必需

所以我真的不知道为什么protoc不能编译它。这里还有另一个讨论。答案表明地图只是proto 3的一个特征。这与谷歌的文档相矛盾。

嗯。例如,您的proto实际上是:

message Dictionary {
    map<string, string> pairs = 1;
}
消息字典{
映射对=1;
}
好消息是,对于您定义的键和值字段,它与现有数据完全向后兼容:)

坏消息是我不知道protobuf net是否支持它。如果您实际上没有在.NET端使用
.proto
文件,并且以声明的方式执行所有操作,那么您可以修改
.proto
文件,重新生成Java代码,然后继续


剩下的坏消息是,地图是在v3.0中引入的,在撰写本文时,v3.0仍处于alpha/beta版本。现在,根据您需要发布的时间,您可能会决定押注v3.0在您需要的时候发布——在我看来,拥有良好的映射语法的好处非常重要。目前正在进行的大多数更改都是围绕新的proto3特性进行的,而proto2语法文件中也允许使用映射。。。只是您需要v3.0编译器和运行时来使用它们。

如果您使用的是proto3,则可以使用映射@AndyTurner:proto2也支持贴图。它们是与proto3同时引入的,但是您不必使用proto3语法文件来使用它们。谢谢,Jon。是的,我不认为protobuf网络支持它。如果存在字典类型,它将生成重复的键值对类型,而不是映射。正如您所猜测的,protobuf在.NET端被定义为注释。我们必须使用protobuf-net从代码生成to.proto文件,并手动(大量)进行修改。我将验证向后兼容性部分并报告。我尝试了您的建议,在addressbook示例中添加了一个map字段。但是protoc抛出了错误addressbook.proto:31:5:预期为“必需”、“可选”或“重复”。addressbook.proto:31:8:应为字段名。我的protoc版本是2.6.1。请看,它报告了同样的问题。@Lan:您需要一个更新版本的protoc。我将编辑以澄清这一点。我在阅读邮件列表上的一些帖子后得出了相同的结论。在下载Protobuf3Alpha3之后,我可以让地图工作了。而且它似乎是向后兼容的。谢谢你的帮助
message Dictionary {
    map<string, string> pairs = 1;
}