user462455
user462455

Reputation: 13588

Protobuf objects as Keys in Maps

Can we use protobuf class ( objects generated from protobuf compiler) as keys in HashMaps.

How is the hashCode() implemented on a protobuf class. Is the hashcode() method good enough to avoid collisions most of the time.

Upvotes: 8

Views: 6645

Answers (2)

Carl Mastrangelo
Carl Mastrangelo

Reputation: 6628

You can, but you should be aware that there are issues with doing so. In Proto2, optional fields and extensions can cause some surprising effects. For example, consider the following proto:

message Foo {
  optional string bar = 1;
}

And consider the following code:

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

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

What will the size of s be? In this case, it will be 2, but if you compared each field directly you would find them the same:

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

All the fields of the two have the same value, but they won't compare equal. The equals and hashCode methods take whether or not a field is set into account, even if the default value is the same as the set value. This also is why you sometimes see unit tests report that two protos are not equal, when their string representations are the same.

One other thing to consider is that Protobuf extensions have an effect on equality between two protos. If the same proto is parsed with an extension registry and without one, the two representations will not compare equal. This may surprising, since their encoded wire format is identical, and are are both parsed as the same message type. In the case of the proto parsed without and extension registry, the extra data will show up in the unknown fields.

This is all obvious if you know how Protobuf works, but may not be so to a newcomer.

Upvotes: 7

Louis Wasserman
Louis Wasserman

Reputation: 198023

Yes, you can use protocol buffers as hash keys. Protocol buffer message types implement Message, which specifies a content-dependent equals and hashCode implementation.

Upvotes: 3

Related Questions