Protobuf对象作为地图中的键

时间:2016-01-11 19:56:59

标签: java scala protocol-buffers grpc

我们可以使用protobuf类(从protobuf编译器生成的对象)作为HashMaps中的键。

如何在protobuf类上实现hashCode()。 hashcode()方法是否足够好以避免在大多数时间发生冲突。

2 个答案:

答案 0 :(得分:4)

你可以,但你应该知道这样做有问题。在Proto2中,可选字段和扩展可能会产生一些令人惊讶的效果。例如,请考虑以下原型:

message Foo {
  optional string bar = 1;
}

并考虑以下代码:

Foo thing1 = Foo.newBuilder().setBar("").build();
Foo thing2 = Foo.getDefaultInstance();

Set<Foo> s = new HashSet<>();
s.add(thing1);
s.add(thing2);

s的大小是多少?在这种情况下,它将是2,但如果你直接比较每个字段,你会发现它们是相同的:

assertEquals(thing1.getBar(), thing2.getBar()); // true

两者的所有字段都具有相同的值,但它们不会相等。即使默认值与设置值相同,equalshashCode方法也会考虑是否设置了字段。这也是为什么你有时看到单元测试报告两个protos不相等,当他们的字符串表示是相同的。

另一件需要考虑的事情是Protobuf扩展对两个protos之间的平等有影响。如果使用扩展注册表解析相同的proto并且没有一个,则两个表示将不会相等。这可能令人惊讶,因为它们的编码线格式是相同的,并且都被解析为相同的消息类型。在proto解析没有和扩展注册表的情况下,额外的数据将显示在未知字段中。

如果您知道Protobuf是如何工作的,那么这一点就很明显了,但对新手来说可能并非如此。

答案 1 :(得分:2)

是的,您可以使用协议缓冲区作为哈希键。协议缓冲区消息类型实现Messagespecifies内容依赖equalshashCode实现。