java 如何在 ProtoBuf 中高效地对 HashMap/Dictionary 建模
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32187278/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to model HashMap/Dictionary in the ProtoBuf efficiently
提问by Lan
I have a protobuf file serialized by .NET code and I would like to consume it into Java. In the .NET code, there is Dictionary data type and the proto schema looks like
我有一个由 .NET 代码序列化的 protobuf 文件,我想将它使用到 Java 中。在 .NET 代码中,有 Dictionary 数据类型,原型架构看起来像
message Pair {
optional string key = 1;
optional string value = 2;
}
message Dictionary {
repeated Pair pairs = 1;
}
Just as described in stackoverflow post Dictionary in protocol buffers.
正如协议缓冲区中的 stackoverflow post Dictionary 中所述 。
I can use protoc to compile the proto file into Java classes fine. I can deserialize the protobuf file into Java objects successfully. The only problem is that it translates to a Listof Pair objects in Java instead of HashMap. Of course, I still have all the data, but I cannot access the data as efficiently as I prefer. If I have the value of the key, I have to loop through the whole list to get its corresponding value. This does not seem to be optimal.
我可以使用 protoc 将 proto 文件编译成 Java 类。我可以成功地将 protobuf 文件反序列化为 Java 对象。唯一的问题是它转换为Java 中的 Pair 对象列表而不是HashMap。当然,我仍然拥有所有数据,但我无法像我喜欢的那样高效地访问数据。如果我有键的值,我必须遍历整个列表以获取其对应的值。这似乎不是最优的。
I am wondering if there is a better way to model Dictionary/Map data type in the protobuf.
我想知道是否有更好的方法在 protobuf 中对 Dictionary/Map 数据类型进行建模。
Thanks
谢谢
Update:
更新:
I tried Jon Skeet's suggestion to add map type field in the addressbook example and still ran into issue.
我尝试了 Jon Skeet 的建议,在地址簿示例中添加地图类型字段,但仍然遇到问题。
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;
}
The protoc throws error when compiling
protoc 编译时抛出错误
addressbook.proto:25:3: Expected "required", "optional", or "repeated".
addressbook.proto:25:6: Expected field name.
According to Google protobuf doc, proto 2 does support map type https://developers.google.com/protocol-buffers/docs/proto#maps. As I quote,
根据 Google protobuf doc,proto 2 确实支持地图类型https://developers.google.com/protocol-buffers/docs/proto#maps。正如我引用的那样,
Maps cannot be repeated, optional, or required.
地图不能重复、可选或必需。
So I don't really know why protoc cannot compile it. There is another discussion here have to create java pojo for the existing proto includes Map. The answer suggests that map is only a proto 3 feature. This contradicts google's documentation.
所以我真的不知道为什么 protoc 不能编译它。这里还有另一个讨论必须为现有的 proto 包括 Map 创建 java pojo。答案表明 map 只是 proto 3 的功能。这与谷歌的文档相矛盾。
回答by Jon Skeet
Well, maps are already supported in "protobuf proper" as of v3.0. For example, your proto is effectively:
好吧,从 v3.0 开始,“protobuf prop”已经支持映射。例如,您的原型实际上是:
message Dictionary {
map<string, string> pairs = 1;
}
The good news is that with the key and value fields you've defined, that's fully backward-compatible with your existing data :)
好消息是,使用您定义的键和值字段,它与您现有的数据完全向后兼容:)
The bad news is that I don't know whether or not protobuf-net supports it. If you're not actually using the .proto
file on the .NET side, and doing everything declaratively, you may just be able to modify your .proto
file, regenerate the Java code, and go...
坏消息是我不知道 protobuf-net 是否支持它。如果您实际上并未.proto
在 .NET 端使用该文件,而是以声明方式执行所有操作,则您可能只能修改.proto
文件、重新生成 Java 代码,然后……
The remaining bad news is that maps were introduced in v3.0 which is still in alpha/beta at the time of this writing. Now, depending on when you need to ship, you may decide to bet on v3.0 being released by the time you need it - the benefits of having nice map syntax are pretty significant, in my view. Most of the changes being made at the moment are around the new proto3 features - whereas maps are allowed within proto2 syntax files too... it's just that you need the v3.0 compiler and runtime to use them.
剩下的坏消息是地图是在 v3.0 中引入的,在撰写本文时仍处于 alpha/beta 阶段。现在,根据您需要发布的时间,您可以决定押注 v3.0 在您需要的时候发布——在我看来,拥有良好地图语法的好处非常显着。目前所做的大部分更改都围绕着新的 proto3 功能 - 而 proto2 语法文件中也允许使用地图……只是您需要 v3.0 编译器和运行时才能使用它们。