aboutsummaryrefslogtreecommitdiffhomepage
path: root/java/src/main/java/com/google/protobuf/AbstractMessage.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/main/java/com/google/protobuf/AbstractMessage.java')
-rw-r--r--java/src/main/java/com/google/protobuf/AbstractMessage.java60
1 files changed, 58 insertions, 2 deletions
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java
index fb416bdc..b9d83016 100644
--- a/java/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -32,9 +32,10 @@ package com.google.protobuf;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Internal.EnumLite;
-import java.io.InputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -167,11 +168,66 @@ public abstract class AbstractMessage extends AbstractMessageLite
public int hashCode() {
int hash = 41;
hash = (19 * hash) + getDescriptorForType().hashCode();
- hash = (53 * hash) + getAllFields().hashCode();
+ hash = hashFields(hash, getAllFields());
hash = (29 * hash) + getUnknownFields().hashCode();
return hash;
}
+ /** Get a hash code for given fields and values, using the given seed. */
+ @SuppressWarnings("unchecked")
+ protected int hashFields(int hash, Map<FieldDescriptor, Object> map) {
+ for (Map.Entry<FieldDescriptor, Object> entry : map.entrySet()) {
+ FieldDescriptor field = entry.getKey();
+ Object value = entry.getValue();
+ hash = (37 * hash) + field.getNumber();
+ if (field.getType() != FieldDescriptor.Type.ENUM){
+ hash = (53 * hash) + value.hashCode();
+ } else if (field.isRepeated()) {
+ List<? extends EnumLite> list = (List<? extends EnumLite>) value;
+ hash = (53 * hash) + hashEnumList(list);
+ } else {
+ hash = (53 * hash) + hashEnum((EnumLite) value);
+ }
+ }
+ return hash;
+ }
+
+ /**
+ * Helper method for implementing {@link Message#hashCode()}.
+ * @see Boolean#hashCode()
+ */
+ protected static int hashLong(long n) {
+ return (int) (n ^ (n >>> 32));
+ }
+
+ /**
+ * Helper method for implementing {@link Message#hashCode()}.
+ * @see Boolean#hashCode()
+ */
+ protected static int hashBoolean(boolean b) {
+ return b ? 1231 : 1237;
+ }
+
+ /**
+ * Helper method for implementing {@link Message#hashCode()}.
+ * <p>
+ * This is needed because {@link java.lang.Enum#hashCode()} is final, but we
+ * need to use the field number as the hash code to ensure compatibility
+ * between statically and dynamically generated enum objects.
+ */
+ protected static int hashEnum(EnumLite e) {
+ return e.getNumber();
+ }
+
+ /** Helper method for implementing {@link Message#hashCode()}. */
+ protected static int hashEnumList(List<? extends EnumLite> list) {
+ int hash = 1;
+ for (EnumLite e : list) {
+ hash = 31 * hash + hashEnum(e);
+ }
+ return hash;
+ }
+
// =================================================================
/**