This is an automated email from the ASF dual-hosted git repository. opwvhk pushed a commit to branch branch-1.12 in repository https://gitbox.apache.org/repos/asf/avro.git
commit 985922824396a05ceb334b9c64a491734e5ff3d9 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]> (cherry picked from commit c880f4729e0dcb99bab82dd5b5efb15f0da55890) --- .../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 30cd133586..23fe4a63d2 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 c837708765..b315e517f6 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 @@ -218,4 +218,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 04eb11801e..b5940baa85 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 @@ -1139,6 +1139,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 9c3e8dc332..3d877cc495 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; + } }
