我们可以使用 protobuf 类(从 protobuf 编译器生成的对象)作为 HashMaps 中的键。
hashCode() 如何在 protobuf 类上实现。hashcode() 方法是否足以在大多数情况下避免冲突。
我们可以使用 protobuf 类(从 protobuf 编译器生成的对象)作为 HashMaps 中的键。
hashCode() 如何在 protobuf 类上实现。hashcode() 方法是否足以在大多数情况下避免冲突。
你可以,但你应该意识到这样做会有问题。在 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
两者的所有字段都具有相同的值,但它们不会比较相等。equals
andhashCode
方法考虑是否设置了字段,即使默认值与设置值相同。这也是为什么您有时会看到单元测试报告两个原型不相等的原因,而它们的字符串表示相同。
要考虑的另一件事是 Protobuf 扩展对两个 proto 之间的相等性有影响。如果使用扩展注册表解析相同的原型并且没有扩展注册表,则两种表示将不相等。这可能令人惊讶,因为它们的编码线路格式相同,并且都被解析为相同的消息类型。在没有扩展注册表解析的原型的情况下,额外的数据将显示在未知字段中。
如果您知道 Protobuf 是如何工作的,这一切都是显而易见的,但对于新手来说可能并非如此。
是的,您可以使用协议缓冲区作为哈希键。协议缓冲区消息类型 implement Message
,它指定了依赖于内容的equals
实现hashCode
。