7

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

hashCode() 如何在 protobuf 类上实现。hashcode() 方法是否足以在大多数情况下避免冲突。

4

2 回答 2

6

你可以,但你应该意识到这样做会有问题。在 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

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

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

如果您知道 Protobuf 是如何工作的,这一切都是显而易见的,但对于新手来说可能并非如此。

于 2016-01-14T01:02:31.127 回答
3

是的,您可以使用协议缓冲区作为哈希键。协议缓冲区消息类型 implement Message,它指定了依赖于内容的equals实现hashCode

于 2016-01-11T20:07:40.137 回答