This is an automated email from the ASF dual-hosted git repository.
opwvhk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/avro.git
The following commit(s) were added to refs/heads/main by this push:
new c880f4729e AVRO-3527: codegen equals and hashCode for Records (#1708)
c880f4729e is described below
commit c880f4729e0dcb99bab82dd5b5efb15f0da55890
Author: Steven Aerts <[email protected]>
AuthorDate: Tue Jun 10 13:48:18 2025 +0200
AVRO-3527: codegen equals and hashCode for Records (#1708)
Update the compiler to generate the implementation of the `.equals()`
and `.hashCode() function, instead of relying on the
implementation of GenericData. This improves the performance of
those functions significantly.
The generated implementations are factor 10 to 20 faster for
`.equals()` and a factor 5 to 10 for `.hashCode()`.
Result of Perf test before the change:
```
Benchmark Mode Cnt Score Error Units
SpecficTest.equals thrpt 3 12598610.194 +/- 11160265.279 ops/s
SpecficTest.hashCode thrpt 3 24729446.862 +/- 29051332.794 ops/s
```
Results using generated functions:
```
Benchmark Mode Cnt Score Error Units
SpecficTest.equals thrpt 3 211314296.950 +/- 104154793.126 ops/s
SpecficTest.hashCode thrpt 3 180349506.632 +/- 143639246.771 ops/s
```
Signed-off-by: Steven Aerts <[email protected]>
---
.../java/org/apache/avro/generic/GenericData.java | 6 +--
.../src/main/java/org/apache/avro/util/Utf8.java | 24 ++++++++++++
.../avro/compiler/specific/SpecificCompiler.java | 40 ++++++++++++++++++++
.../specific/templates/java/classic/record.vm | 41 ++++++++++++++++++++
.../avro/examples/baseball/FieldTest.java | 44 ++++++++++++++++++++++
.../JSpecifyNullSafeAnnotationsFieldsTest.java | 34 +++++++++++++++++
.../JetBrainsNullSafeAnnotationsFieldsTest.java | 34 +++++++++++++++++
.../avro/examples/baseball/Player.java | 36 ++++++++++++++++++
.../avro/examples/baseball/Proto.java | 2 +-
.../output/AddExtraOptionalGettersTest.java | 28 ++++++++++++++
.../src/test/compiler/output/NoSettersTest.java | 28 ++++++++++++++
.../output/OptionalGettersAllFieldsTest.java | 36 ++++++++++++++++++
.../output/OptionalGettersNullableFieldsTest.java | 38 +++++++++++++++++++
.../tools/src/test/compiler/output/Player.java | 36 ++++++++++++++++++
14 files changed, 423 insertions(+), 4 deletions(-)
diff --git
a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java
b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java
index e85931e699..f327851e5d 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java
@@ -1312,9 +1312,9 @@ public class GenericData {
case NULL:
return 0;
case STRING:
- Utf8 u1 = o1 instanceof Utf8 ? (Utf8) o1 : new Utf8(o1.toString());
- Utf8 u2 = o2 instanceof Utf8 ? (Utf8) o2 : new Utf8(o2.toString());
- return u1.compareTo(u2);
+ CharSequence cs1 = o1 instanceof CharSequence ? (CharSequence) o1 :
o1.toString();
+ CharSequence cs2 = o2 instanceof CharSequence ? (CharSequence) o2 :
o2.toString();
+ return Utf8.compareSequences(cs1, cs2);
default:
return ((Comparable) o1).compareTo(o2);
}
diff --git a/lang/java/avro/src/main/java/org/apache/avro/util/Utf8.java
b/lang/java/avro/src/main/java/org/apache/avro/util/Utf8.java
index b609e166c7..5e5af1a111 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/util/Utf8.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/util/Utf8.java
@@ -230,4 +230,28 @@ public class Utf8 implements Comparable<Utf8>,
CharSequence, Externalizable {
setByteLength(in.readInt());
in.readFully(bytes);
}
+
+ public static int compareSequences(CharSequence cs1, CharSequence cs2) {
+ if (cs1 == cs2) {
+ return 0;
+ }
+
+ if (cs1 == null || cs2 == null) {
+ return cs1 == null ? 1 : -1;
+ }
+
+ if (cs1.getClass() == cs2.getClass() && cs1 instanceof Comparable) {
+ return ((Comparable<Object>) cs1).compareTo(cs2);
+ }
+
+ for (int i = 0, len = Math.min(cs1.length(), cs2.length()); i < len; i++) {
+ char a = cs1.charAt(i);
+ char b = cs2.charAt(i);
+ if (a != b) {
+ return a - b;
+ }
+ }
+
+ return cs1.length() - cs2.length();
+ }
}
diff --git
a/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java
b/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java
index bf1b63e98f..ea1e1a11b5 100644
---
a/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java
+++
b/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java
@@ -1166,6 +1166,46 @@ public class SpecificCompiler {
return SpecificData.mangle(word, reservedWords, isMethod);
}
+ public boolean canGenerateEqualsAndHashCode(Schema schema) {
+ return getUsedCustomLogicalTypeFactories(schema).isEmpty();
+ }
+
+ public boolean isPrimitiveType(Schema schema) {
+ return !isUnboxedJavaTypeNullable(schema) &&
getConvertedLogicalType(schema) == null;
+ }
+
+ public String hashCodeFor(Schema schema, String name) {
+ switch (javaUnbox(schema, false)) {
+ case "int":
+ return "Integer.hashCode(" + name + ")";
+ case "long":
+ return "Long.hashCode(" + name + ")";
+ case "float":
+ return "Float.hashCode(" + name + ")";
+ case "double":
+ return "Double.hashCode(" + name + ")";
+ case "boolean":
+ return "Boolean.hashCode(" + name + ")";
+ default:
+ // Hashcode of Union is expected to match ordinal
+ if (schema.getType() == Schema.Type.ENUM || ((schema.getType() ==
Schema.Type.UNION)
+ && (schema.getTypes().stream().anyMatch(t -> t.getType() ==
Schema.Type.ENUM)))) {
+ if (schema.getType() == Schema.Type.ENUM
+ || (schema.getTypes().size() == 2 &&
schema.getTypes().contains(NULL_SCHEMA))) {
+ return "(" + name + " == null ? 0 : ((java.lang.Enum) " + name +
").ordinal())";
+ } else {
+ return "(" + name + " == null ? 0 : " + name + " instanceof
java.lang.Enum ? ((java.lang.Enum) " + name
+ + ").ordinal() : " + name + ".hashCode())";
+ }
+ }
+ return "(" + name + " == null ? 0 : " + name + ".hashCode())";
+ }
+ }
+
+ public boolean ignoredField(Field field) {
+ return field.order() == Field.Order.IGNORE;
+ }
+
/**
* Utility for use by templates. Return schema fingerprint as a long.
*/
diff --git
a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm
b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm
index d08f099ec9..2c26d472fb 100755
---
a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm
+++
b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm
@@ -616,6 +616,47 @@ public class
${this.mangleTypeIdentifier($schema.getName())} extends ${this.getS
}
}
#end
+#if ($this.canGenerateEqualsAndHashCode($schema))
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+#foreach ($field in $schema.getFields())
+#if (!${this.ignoredField($field)})
+#set ($n = ${this.mangle($field.name(), $schema.isError())})
+ result = 31 * result + ${this.hashCodeFor($field.schema(), $n)};
+#end
+#end
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof ${this.mangleTypeIdentifier($schema.getName())})) {
+ return false;
+ }
+ ${this.mangleTypeIdentifier($schema.getName())} other =
(${this.mangleTypeIdentifier($schema.getName())}) o;
+#foreach ($field in $schema.getFields())
+#if (!${this.ignoredField($field)})
+#set ($n = ${this.mangle($field.name(), $schema.isError())})
+#set ($s = $field.schema())
+#if (${this.isPrimitiveType($s)})
+ if (this.$n != other.$n) {
+#elseif (${this.javaType($field.schema()).equals("java.lang.CharSequence")})
+ if (Utf8.compareSequences(this.$n, other.$n) != 0) {
+#else
+ if (!java.util.Objects.equals(this.$n, other.$n)) {
+#end
+ return false;
+ }
+#end
+#end
+ return true;
+ }
+#end
}
#macro( encodeVar $indent $var $s )
diff --git
a/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/FieldTest.java
b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/FieldTest.java
index 6e69cd3df4..8799e202fc 100644
---
a/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/FieldTest.java
+++
b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/FieldTest.java
@@ -15,6 +15,8 @@ import org.apache.avro.message.SchemaStore;
@org.apache.avro.specific.AvroGenerated
public class FieldTest extends org.apache.avro.specific.SpecificRecordBase
implements org.apache.avro.specific.SpecificRecord {
private static final long serialVersionUID = 4609235620572341636L;
+
+
public static final org.apache.avro.Schema SCHEMA$ = new
org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"FieldTest\",\"namespace\":\"avro.examples.baseball\",\"doc\":\"Test
various field
types\",\"fields\":[{\"name\":\"number\",\"type\":\"int\",\"doc\":\"The number
of the
player\"},{\"name\":\"last_name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"timestamp\",\"type\":{\"type\":\"long\",\"logicalType\":\"timestamp-millis\"}},{\"na
[...]
public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; }
@@ -659,6 +661,48 @@ public class FieldTest extends
org.apache.avro.specific.SpecificRecordBase imple
READER$.read(this, SpecificData.getDecoder(in));
}
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + Integer.hashCode(number);
+ result = 31 * result + (last_name == null ? 0 : last_name.hashCode());
+ result = 31 * result + (timestamp == null ? 0 : timestamp.hashCode());
+ result = 31 * result + (timestampMicros == null ? 0 :
timestampMicros.hashCode());
+ result = 31 * result + (timeMillis == null ? 0 : timeMillis.hashCode());
+ result = 31 * result + (timeMicros == null ? 0 : timeMicros.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof FieldTest)) {
+ return false;
+ }
+ FieldTest other = (FieldTest) o;
+ if (this.number != other.number) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.last_name, other.last_name)) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.timestamp, other.timestamp)) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.timestampMicros,
other.timestampMicros)) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.timeMillis, other.timeMillis)) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.timeMicros, other.timeMicros)) {
+ return false;
+ }
+ return true;
+ }
}
diff --git
a/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/JSpecifyNullSafeAnnotationsFieldsTest.java
b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/JSpecifyNullSafeAnnotationsFieldsTest.java
index 7a352b703d..e99e04dc52 100644
---
a/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/JSpecifyNullSafeAnnotationsFieldsTest.java
+++
b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/JSpecifyNullSafeAnnotationsFieldsTest.java
@@ -581,6 +581,40 @@ public class JSpecifyNullSafeAnnotationsFieldsTest extends
org.apache.avro.speci
}
}
}
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + (name == null ? 0 : name.hashCode());
+ result = 31 * result + (nullable_name == null ? 0 :
nullable_name.hashCode());
+ result = 31 * result + Integer.hashCode(favorite_number);
+ result = 31 * result + (nullable_favorite_number == null ? 0 :
nullable_favorite_number.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof JSpecifyNullSafeAnnotationsFieldsTest)) {
+ return false;
+ }
+ JSpecifyNullSafeAnnotationsFieldsTest other =
(JSpecifyNullSafeAnnotationsFieldsTest) o;
+ if (!java.util.Objects.equals(this.name, other.name)) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.nullable_name, other.nullable_name)) {
+ return false;
+ }
+ if (this.favorite_number != other.favorite_number) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.nullable_favorite_number,
other.nullable_favorite_number)) {
+ return false;
+ }
+ return true;
+ }
}
diff --git
a/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/JetBrainsNullSafeAnnotationsFieldsTest.java
b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/JetBrainsNullSafeAnnotationsFieldsTest.java
index 5e898c8847..7df11818f5 100644
---
a/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/JetBrainsNullSafeAnnotationsFieldsTest.java
+++
b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/JetBrainsNullSafeAnnotationsFieldsTest.java
@@ -581,6 +581,40 @@ public class JetBrainsNullSafeAnnotationsFieldsTest
extends org.apache.avro.spec
}
}
}
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + (name == null ? 0 : name.hashCode());
+ result = 31 * result + (nullable_name == null ? 0 :
nullable_name.hashCode());
+ result = 31 * result + Integer.hashCode(favorite_number);
+ result = 31 * result + (nullable_favorite_number == null ? 0 :
nullable_favorite_number.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof JetBrainsNullSafeAnnotationsFieldsTest)) {
+ return false;
+ }
+ JetBrainsNullSafeAnnotationsFieldsTest other =
(JetBrainsNullSafeAnnotationsFieldsTest) o;
+ if (!java.util.Objects.equals(this.name, other.name)) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.nullable_name, other.nullable_name)) {
+ return false;
+ }
+ if (this.favorite_number != other.favorite_number) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.nullable_favorite_number,
other.nullable_favorite_number)) {
+ return false;
+ }
+ return true;
+ }
}
diff --git
a/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Player.java
b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Player.java
index 1821e41cbe..79fc55dbf9 100644
---
a/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Player.java
+++
b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Player.java
@@ -15,6 +15,8 @@ import org.apache.avro.message.SchemaStore;
@org.apache.avro.specific.AvroGenerated
public class Player extends org.apache.avro.specific.SpecificRecordBase
implements org.apache.avro.specific.SpecificRecord {
private static final long serialVersionUID = 3865593031278745715L;
+
+
public static final org.apache.avro.Schema SCHEMA$ = new
org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"Player\",\"namespace\":\"avro.examples.baseball\",\"doc\":\"選手
is Japanese for
player.\",\"fields\":[{\"name\":\"number\",\"type\":\"int\",\"doc\":\"The
number of the
player\"},{\"name\":\"first_name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"last_name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\
[...]
public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; }
@@ -587,6 +589,40 @@ public class Player extends
org.apache.avro.specific.SpecificRecordBase implemen
}
}
}
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + Integer.hashCode(number);
+ result = 31 * result + (first_name == null ? 0 : first_name.hashCode());
+ result = 31 * result + (last_name == null ? 0 : last_name.hashCode());
+ result = 31 * result + (position == null ? 0 : position.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof Player)) {
+ return false;
+ }
+ Player other = (Player) o;
+ if (this.number != other.number) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.first_name, other.first_name)) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.last_name, other.last_name)) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.position, other.position)) {
+ return false;
+ }
+ return true;
+ }
}
diff --git
a/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Proto.java
b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Proto.java
index def7bca42b..45c104530d 100644
---
a/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Proto.java
+++
b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Proto.java
@@ -24,4 +24,4 @@ public interface Proto {
*/
void bar(org.apache.avro.ipc.Callback<java.lang.Void> callback) throws
java.io.IOException;
}
-}
+}
\ No newline at end of file
diff --git
a/lang/java/tools/src/test/compiler/output/AddExtraOptionalGettersTest.java
b/lang/java/tools/src/test/compiler/output/AddExtraOptionalGettersTest.java
index d8c5361848..328091ac8b 100644
--- a/lang/java/tools/src/test/compiler/output/AddExtraOptionalGettersTest.java
+++ b/lang/java/tools/src/test/compiler/output/AddExtraOptionalGettersTest.java
@@ -15,6 +15,8 @@ import java.util.Optional;
@org.apache.avro.specific.AvroGenerated
public class AddExtraOptionalGettersTest extends
org.apache.avro.specific.SpecificRecordBase implements
org.apache.avro.specific.SpecificRecord {
private static final long serialVersionUID = -3300987256178011215L;
+
+
public static final org.apache.avro.Schema SCHEMA$ = new
org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"AddExtraOptionalGettersTest\",\"namespace\":\"avro.examples.baseball\",\"doc\":\"Test
that extra optional getters are
added\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"int\",\"null\"]}]}");
public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; }
@@ -428,6 +430,32 @@ public class AddExtraOptionalGettersTest extends
org.apache.avro.specific.Specif
}
}
}
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + (name == null ? 0 : name.hashCode());
+ result = 31 * result + (favorite_number == null ? 0 :
favorite_number.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof AddExtraOptionalGettersTest)) {
+ return false;
+ }
+ AddExtraOptionalGettersTest other = (AddExtraOptionalGettersTest) o;
+ if (Utf8.compareSequences(this.name, other.name) != 0) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.favorite_number,
other.favorite_number)) {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/lang/java/tools/src/test/compiler/output/NoSettersTest.java
b/lang/java/tools/src/test/compiler/output/NoSettersTest.java
index 6e4cea44f8..92c91854cf 100644
--- a/lang/java/tools/src/test/compiler/output/NoSettersTest.java
+++ b/lang/java/tools/src/test/compiler/output/NoSettersTest.java
@@ -15,6 +15,8 @@ import org.apache.avro.message.SchemaStore;
@org.apache.avro.specific.AvroGenerated
public class NoSettersTest extends org.apache.avro.specific.SpecificRecordBase
implements org.apache.avro.specific.SpecificRecord {
private static final long serialVersionUID = 8604146783520861700L;
+
+
public static final org.apache.avro.Schema SCHEMA$ = new
org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"NoSettersTest\",\"namespace\":\"avro.examples.baseball\",\"doc\":\"Test
that setters are
omitted\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"favorite_number\",\"type\":[\"int\",\"null\"]}]}");
public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; }
@@ -386,6 +388,32 @@ public class NoSettersTest extends
org.apache.avro.specific.SpecificRecordBase i
}
}
}
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + (name == null ? 0 : name.hashCode());
+ result = 31 * result + (favorite_number == null ? 0 :
favorite_number.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof NoSettersTest)) {
+ return false;
+ }
+ NoSettersTest other = (NoSettersTest) o;
+ if (Utf8.compareSequences(this.name, other.name) != 0) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.favorite_number,
other.favorite_number)) {
+ return false;
+ }
+ return true;
+ }
}
diff --git
a/lang/java/tools/src/test/compiler/output/OptionalGettersAllFieldsTest.java
b/lang/java/tools/src/test/compiler/output/OptionalGettersAllFieldsTest.java
index ece62933a8..0194aeaed0 100644
--- a/lang/java/tools/src/test/compiler/output/OptionalGettersAllFieldsTest.java
+++ b/lang/java/tools/src/test/compiler/output/OptionalGettersAllFieldsTest.java
@@ -15,6 +15,8 @@ import java.util.Optional;
@org.apache.avro.specific.AvroGenerated
public class OptionalGettersAllFieldsTest extends
org.apache.avro.specific.SpecificRecordBase implements
org.apache.avro.specific.SpecificRecord {
private static final long serialVersionUID = 874861432798554536L;
+
+
public static final org.apache.avro.Schema SCHEMA$ = new
org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"OptionalGettersAllFieldsTest\",\"namespace\":\"avro.examples.baseball\",\"doc\":\"Test
that optional getters are created for all
fields\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"nullable_name\",\"type\":[\"string\",\"null\"]},{\"name\":\"favorite_number\",\"type\":[\"int\"]},{\"name\":\"nullable_favorite_number\",\"type\":[\"int\",\"nul
[...]
public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; }
@@ -491,6 +493,40 @@ public class OptionalGettersAllFieldsTest extends
org.apache.avro.specific.Speci
READER$.read(this, SpecificData.getDecoder(in));
}
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + (name == null ? 0 : name.hashCode());
+ result = 31 * result + (nullable_name == null ? 0 :
nullable_name.hashCode());
+ result = 31 * result + (favorite_number == null ? 0 :
favorite_number.hashCode());
+ result = 31 * result + (nullable_favorite_number == null ? 0 :
nullable_favorite_number.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof OptionalGettersAllFieldsTest)) {
+ return false;
+ }
+ OptionalGettersAllFieldsTest other = (OptionalGettersAllFieldsTest) o;
+ if (Utf8.compareSequences(this.name, other.name) != 0) {
+ return false;
+ }
+ if (Utf8.compareSequences(this.nullable_name, other.nullable_name) != 0) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.favorite_number,
other.favorite_number)) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.nullable_favorite_number,
other.nullable_favorite_number)) {
+ return false;
+ }
+ return true;
+ }
}
diff --git
a/lang/java/tools/src/test/compiler/output/OptionalGettersNullableFieldsTest.java
b/lang/java/tools/src/test/compiler/output/OptionalGettersNullableFieldsTest.java
index 60c87c2953..ad9b9c3863 100644
---
a/lang/java/tools/src/test/compiler/output/OptionalGettersNullableFieldsTest.java
+++
b/lang/java/tools/src/test/compiler/output/OptionalGettersNullableFieldsTest.java
@@ -565,6 +565,44 @@ public class OptionalGettersNullableFieldsTest extends
org.apache.avro.specific.
READER$.read(this, SpecificData.getDecoder(in));
}
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + (name == null ? 0 : name.hashCode());
+ result = 31 * result + (nullable_name == null ? 0 :
nullable_name.hashCode());
+ result = 31 * result + (favorite_number == null ? 0 :
favorite_number.hashCode());
+ result = 31 * result + (nullable_favorite_number == null ? 0 :
nullable_favorite_number.hashCode());
+ result = 31 * result + (nullable_array == null ? 0 :
nullable_array.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof OptionalGettersNullableFieldsTest)) {
+ return false;
+ }
+ OptionalGettersNullableFieldsTest other =
(OptionalGettersNullableFieldsTest) o;
+ if (Utf8.compareSequences(this.name, other.name) != 0) {
+ return false;
+ }
+ if (Utf8.compareSequences(this.nullable_name, other.nullable_name) != 0) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.favorite_number,
other.favorite_number)) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.nullable_favorite_number,
other.nullable_favorite_number)) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.nullable_array, other.nullable_array)) {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/lang/java/tools/src/test/compiler/output/Player.java
b/lang/java/tools/src/test/compiler/output/Player.java
index e1f6f91c84..adc1e2be7f 100644
--- a/lang/java/tools/src/test/compiler/output/Player.java
+++ b/lang/java/tools/src/test/compiler/output/Player.java
@@ -15,6 +15,8 @@ import org.apache.avro.message.SchemaStore;
@org.apache.avro.specific.AvroGenerated
public class Player extends org.apache.avro.specific.SpecificRecordBase
implements org.apache.avro.specific.SpecificRecord {
private static final long serialVersionUID = 3865593031278745715L;
+
+
public static final org.apache.avro.Schema SCHEMA$ = new
org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"Player\",\"namespace\":\"avro.examples.baseball\",\"doc\":\"選手
is Japanese for
player.\",\"fields\":[{\"name\":\"number\",\"type\":\"int\",\"doc\":\"The
number of the
player\"},{\"name\":\"first_name\",\"type\":\"string\"},{\"name\":\"last_name\",\"type\":\"string\"},{\"name\":\"position\",\"type\":{\"type\":\"array\",\"items\":{\"type\":\"enum\",\"name\":\"Po
[...]
public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; }
@@ -587,6 +589,40 @@ public class Player extends
org.apache.avro.specific.SpecificRecordBase implemen
}
}
}
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + Integer.hashCode(number);
+ result = 31 * result + (first_name == null ? 0 : first_name.hashCode());
+ result = 31 * result + (last_name == null ? 0 : last_name.hashCode());
+ result = 31 * result + (position == null ? 0 : position.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof Player)) {
+ return false;
+ }
+ Player other = (Player) o;
+ if (this.number != other.number) {
+ return false;
+ }
+ if (Utf8.compareSequences(this.first_name, other.first_name) != 0) {
+ return false;
+ }
+ if (Utf8.compareSequences(this.last_name, other.last_name) != 0) {
+ return false;
+ }
+ if (!java.util.Objects.equals(this.position, other.position)) {
+ return false;
+ }
+ return true;
+ }
}