当前位置: 首页 > 知识库问答 >
问题:

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

商同化
2023-03-14

我有一个由.NET代码序列化的protobuf文件,我想把它用到Java中。在.NET代码中,有字典数据类型,并且proto模式类似于

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

message Dictionary {
   repeated Pair pairs = 1;
}

正如协议缓冲区中的stackoverflow post字典中所述。

我可以使用protoc将原始文件编译成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;
}

protoc在编译时抛出错误

addressbook.proto:25:3: Expected "required", "optional", or "repeated".
addressbook.proto:25:6: Expected field name.

根据Google protobuf文档,Proto2支持类型为https://developers.Google.com/protocol-buffers/docs/proto#maps的地图。正如我所引述那样,

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

所以我真的不知道为什么protoc不能编译它。这里还有一个讨论,必须为现有的proto includes map创建Java pojo。答案表明map只是Proto3的一个特性。这与谷歌的文档相矛盾。

共有1个答案

张翰音
2023-03-14

好吧,从V3.0开始,“protobuf proper”就已经支持地图了。例如,您的proto有效地:

message Dictionary {
    map<string, string> pairs = 1;
}

好消息是,使用您定义的key和value字段,它与现有数据完全向后兼容:)

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

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

 类似资料:
  • 我定义了一个简单的迷你。原型文件如下: protoc编译器(--version==libprotoc 3.0.0,从protobuf-python-3.0.0-alpha-3的源代码安装)报告:

  • 我正在用Protobuf在golang写一个新的服务。我想在.proto文件中对以下请求JSON建模。 目前存在两个问题: 每个数组元素中的键事先是不知道的,因此我不能在.proto文件中创建消息并重复它。我需要保持它的映射 我无法对json建模,因为它只是一个没有键的数组。每次执行此操作时,都会显示以下错误:解码请求失败:JSON:无法将数组反编入Go值 以下是我的.proto文件: 我尝试过使

  • 问题内容: 这是我目前的方式。有什么办法可以使用矩阵运算吗?X是数据点。 问题答案: 您是否要使用高斯核进行图像平滑?如果是这样,则scipy中有一个函数: 更新的答案 这应该可以工作- 尽管仍不能100%准确,但它会尝试考虑网格每个像元内的概率质量。我认为在每个像元的中点使用概率密度的准确性稍差,尤其是对于小内核。有关示例,请参见https://homepages.inf.ed.ac.uk/rb

  • 我有两个收藏品。 null 员额 post_id user_id 主题 正文 附件 创建_at 更新_at (User和Posts集合都有2000000个文档) null 所以我先提取过滤过的用户。 并通过过滤的用户提取帖子。 但随着服务的成长,帖子和用户数据将会增加。 这里有其他性能改进吗? 任何建议,非常感谢。

  • 我有INT数组 我也在寻找类似的问题,但我只发现了java.util.stream.stream .sorted()的大O复杂性,这一点也没有帮助,因为有两个不同的答案(第一个当然是部分错误的,因为arrays.sort并不总是O(n log n))。第二个呢?我还没找到证据。

  • 有两个类。我想在dataConsumer类中获取数据提供程序类providerData_。 为了解决这种情况,我认为下面是一个解决方案。我制作了如下的singleton数据传输类。但我不确定这是不是c中的通用解,首先我想知道我的解是否可用。接下来,如果你知道更好的解决方案(或设计模式)来解决我的情况,请告诉我。