8311188: Simplify and modernize equals and hashCode in java.text

Reviewed-by: lancea, naoto, rriggs
This commit is contained in:
Pavel Rappo 2023-07-18 15:12:09 +00:00
parent 1fc726a8b3
commit 1dfb0fb3e2
15 changed files with 72 additions and 98 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -618,7 +618,7 @@ public class AttributedString {
int currIndex = runIndex; int currIndex = runIndex;
int runStart = runStarts[currIndex]; int runStart = runStarts[currIndex];
while (runStart >= beginIndex && while (runStart >= beginIndex &&
valuesMatch(value, getAttribute(attribute, currIndex - 1))) { Objects.equals(value, getAttribute(attribute, currIndex - 1))) {
currIndex--; currIndex--;
runStart = runStarts[currIndex]; runStart = runStarts[currIndex];
} }
@ -632,7 +632,7 @@ public class AttributedString {
int currIndex = runIndex; int currIndex = runIndex;
int runLimit = (currIndex < runCount - 1) ? runStarts[currIndex + 1] : textLength; int runLimit = (currIndex < runCount - 1) ? runStarts[currIndex + 1] : textLength;
while (runLimit <= endIndex && while (runLimit <= endIndex &&
valuesMatch(value, getAttribute(attribute, currIndex + 1))) { Objects.equals(value, getAttribute(attribute, currIndex + 1))) {
currIndex++; currIndex++;
runLimit = (currIndex < runCount - 1) ? runStarts[currIndex + 1] : textLength; runLimit = (currIndex < runCount - 1) ? runStarts[currIndex + 1] : textLength;
} }
@ -650,22 +650,13 @@ public class AttributedString {
// returns whether all specified attributes have equal values in the runs with the given indices // returns whether all specified attributes have equal values in the runs with the given indices
private boolean attributeValuesMatch(Set<? extends Attribute> attributes, int runIndex1, int runIndex2) { private boolean attributeValuesMatch(Set<? extends Attribute> attributes, int runIndex1, int runIndex2) {
for (Attribute key : attributes) { for (Attribute key : attributes) {
if (!valuesMatch(getAttribute(key, runIndex1), getAttribute(key, runIndex2))) { if (!Objects.equals(getAttribute(key, runIndex1), getAttribute(key, runIndex2))) {
return false; return false;
} }
} }
return true; return true;
} }
// returns whether the two objects are either both null or equal
private static final boolean valuesMatch(Object value1, Object value2) {
if (value1 == null) {
return value2 == null;
} else {
return value1.equals(value2);
}
}
/** /**
* Appends the contents of the CharacterIterator iterator into the * Appends the contents of the CharacterIterator iterator into the
* StringBuilder buf. * StringBuilder buf.
@ -760,6 +751,7 @@ public class AttributedString {
// Object methods. See documentation in that class. // Object methods. See documentation in that class.
@Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) { if (this == obj) {
return true; return true;
@ -775,6 +767,7 @@ public class AttributedString {
return true; return true;
} }
@Override
public int hashCode() { public int hashCode() {
return text.hashCode() ^ currentIndex ^ beginIndex ^ endIndex; return text.hashCode() ^ currentIndex ^ beginIndex ^ endIndex;
} }
@ -861,7 +854,7 @@ public class AttributedString {
int runStart = currentRunStart; int runStart = currentRunStart;
int runIndex = currentRunIndex; int runIndex = currentRunIndex;
while (runStart > beginIndex && while (runStart > beginIndex &&
valuesMatch(value, AttributedString.this.getAttribute(attribute, runIndex - 1))) { Objects.equals(value, AttributedString.this.getAttribute(attribute, runIndex - 1))) {
runIndex--; runIndex--;
runStart = runStarts[runIndex]; runStart = runStarts[runIndex];
} }
@ -902,7 +895,7 @@ public class AttributedString {
int runLimit = currentRunLimit; int runLimit = currentRunLimit;
int runIndex = currentRunIndex; int runIndex = currentRunIndex;
while (runLimit < endIndex && while (runLimit < endIndex &&
valuesMatch(value, AttributedString.this.getAttribute(attribute, runIndex + 1))) { Objects.equals(value, AttributedString.this.getAttribute(attribute, runIndex + 1))) {
runIndex++; runIndex++;
runLimit = runIndex < runCount - 1 ? runStarts[runIndex + 1] : endIndex; runLimit = runIndex < runCount - 1 ? runStarts[runIndex + 1] : endIndex;
} }
@ -1081,11 +1074,10 @@ class AttributeEntry implements Map.Entry<Attribute,Object> {
this.value = value; this.value = value;
} }
@Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (!(o instanceof AttributeEntry other)) { return o instanceof AttributeEntry other
return false; && other.key.equals(key) && Objects.equals(other.value, value);
}
return other.key.equals(key) && Objects.equals(other.value, value);
} }
public Attribute getKey() { public Attribute getKey() {
@ -1100,8 +1092,9 @@ class AttributeEntry implements Map.Entry<Attribute,Object> {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public int hashCode() { public int hashCode() {
return key.hashCode() ^ (value==null ? 0 : value.hashCode()); return key.hashCode() ^ Objects.hashCode(value);
} }
public String toString() { public String toString() {

View File

@ -497,6 +497,7 @@ public class ChoiceFormat extends NumberFormat {
/** /**
* Generates a hash code for the message format object. * Generates a hash code for the message format object.
*/ */
@Override
public int hashCode() { public int hashCode() {
int result = choiceLimits.length; int result = choiceLimits.length;
if (choiceFormats.length > 0) { if (choiceFormats.length > 0) {
@ -509,11 +510,11 @@ public class ChoiceFormat extends NumberFormat {
/** /**
* Equality comparison between two * Equality comparison between two
*/ */
@Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj == null) return false;
if (this == obj) // quick check if (this == obj) // quick check
return true; return true;
if (getClass() != obj.getClass()) if (obj == null || getClass() != obj.getClass())
return false; return false;
ChoiceFormat other = (ChoiceFormat) obj; ChoiceFormat other = (ChoiceFormat) obj;
return (Arrays.equals(choiceLimits, other.choiceLimits) return (Arrays.equals(choiceLimits, other.choiceLimits)

View File

@ -530,10 +530,7 @@ public abstract class Collator
if (this == that) { if (this == that) {
return true; return true;
} }
if (that == null) { if (that == null || getClass() != that.getClass()) {
return false;
}
if (getClass() != that.getClass()) {
return false; return false;
} }
Collator other = (Collator) that; Collator other = (Collator) that;

View File

@ -2354,7 +2354,11 @@ public final class CompactNumberFormat extends NumberFormat {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (!super.equals(obj)) { if (this == obj) {
return true;
}
if (!super.equals(obj)) { // super does null and class checks
return false; return false;
} }
@ -2369,9 +2373,7 @@ public final class CompactNumberFormat extends NumberFormat {
} }
/** /**
* Returns the hash code for this {@code CompactNumberFormat} instance. * {@return the hash code for this {@code CompactNumberFormat} instance}
*
* @return hash code for this {@code CompactNumberFormat}
*/ */
@Override @Override
public int hashCode() { public int hashCode() {

View File

@ -683,6 +683,7 @@ public class DateFormatSymbols implements Serializable, Cloneable {
/** /**
* Override equals * Override equals
*/ */
@Override
public boolean equals(Object obj) public boolean equals(Object obj)
{ {
if (this == obj) return true; if (this == obj) return true;
@ -695,10 +696,7 @@ public class DateFormatSymbols implements Serializable, Cloneable {
&& Arrays.equals(shortWeekdays, that.shortWeekdays) && Arrays.equals(shortWeekdays, that.shortWeekdays)
&& Arrays.equals(ampms, that.ampms) && Arrays.equals(ampms, that.ampms)
&& Arrays.deepEquals(getZoneStringsWrapper(), that.getZoneStringsWrapper()) && Arrays.deepEquals(getZoneStringsWrapper(), that.getZoneStringsWrapper())
&& ((localPatternChars != null && Objects.equals(localPatternChars, that.localPatternChars));
&& localPatternChars.equals(that.localPatternChars))
|| (localPatternChars == null
&& that.localPatternChars == null)));
} }
// =======================privates=============================== // =======================privates===============================

View File

@ -2918,10 +2918,13 @@ public class DecimalFormat extends NumberFormat {
@Override @Override
public boolean equals(Object obj) public boolean equals(Object obj)
{ {
if (obj == null) if (this == obj) {
return false; return true;
}
if (!super.equals(obj)) if (!super.equals(obj))
return false; // super does class check return false; // super does null and class checks
DecimalFormat other = (DecimalFormat) obj; DecimalFormat other = (DecimalFormat) obj;
return ((posPrefixPattern == other.posPrefixPattern && return ((posPrefixPattern == other.posPrefixPattern &&
positivePrefix.equals(other.positivePrefix)) positivePrefix.equals(other.positivePrefix))

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -741,9 +741,8 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
*/ */
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj == null) return false;
if (this == obj) return true; if (this == obj) return true;
if (getClass() != obj.getClass()) return false; if (obj == null || getClass() != obj.getClass()) return false;
DecimalFormatSymbols other = (DecimalFormatSymbols) obj; DecimalFormatSymbols other = (DecimalFormatSymbols) obj;
return (zeroDigit == other.zeroDigit && return (zeroDigit == other.zeroDigit &&
groupingSeparator == other.groupingSeparator && groupingSeparator == other.groupingSeparator &&

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -38,6 +38,8 @@
package java.text; package java.text;
import java.util.Objects;
/** /**
* {@code FieldPosition} is a simple class used by {@code Format} * {@code FieldPosition} is a simple class used by {@code Format}
* and its subclasses to identify fields in formatted output. Fields can * and its subclasses to identify fields in formatted output. Fields can
@ -218,28 +220,22 @@ public class FieldPosition {
/** /**
* Overrides equals * Overrides equals
*/ */
@Override
public boolean equals(Object obj) public boolean equals(Object obj)
{ {
if (obj == null) return false;
if (!(obj instanceof FieldPosition other)) if (!(obj instanceof FieldPosition other))
return false; return false;
if (attribute == null) { if (!Objects.equals(attribute, other.attribute))
if (other.attribute != null) {
return false; return false;
}
}
else if (!attribute.equals(other.attribute)) {
return false;
}
return (beginIndex == other.beginIndex return (beginIndex == other.beginIndex
&& endIndex == other.endIndex && endIndex == other.endIndex
&& field == other.field); && field == other.field);
} }
/** /**
* Returns a hash code for this FieldPosition. * {@return a hash code for this FieldPosition}
* @return a hash code value for this object
*/ */
@Override
public int hashCode() { public int hashCode() {
return (field << 24) | (beginIndex << 16) | endIndex; return (field << 24) | (beginIndex << 16) | endIndex;
} }
@ -270,7 +266,7 @@ public class FieldPosition {
/** /**
* Return true if the receiver wants a {@code Format.Field} value and * Return true if the receiver wants a {@code Format.Field} value and
* {@code attribute} is equal to it, or true if the receiver * {@code attribute} is equal to it, or true if the receiver
* represents an inteter constant and {@code field} equals it. * represents an integer constant and {@code field} equals it.
*/ */
private boolean matchesField(Format.Field attribute, int field) { private boolean matchesField(Format.Field attribute, int field) {
if (this.attribute != null) { if (this.attribute != null) {

View File

@ -47,6 +47,7 @@ import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Objects;
/** /**
@ -1132,6 +1133,7 @@ public class MessageFormat extends Format {
/** /**
* Equality comparison between two message format objects * Equality comparison between two message format objects
*/ */
@Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) // quick check if (this == obj) // quick check
return true; return true;
@ -1140,8 +1142,7 @@ public class MessageFormat extends Format {
MessageFormat other = (MessageFormat) obj; MessageFormat other = (MessageFormat) obj;
return (maxOffset == other.maxOffset return (maxOffset == other.maxOffset
&& pattern.equals(other.pattern) && pattern.equals(other.pattern)
&& ((locale != null && locale.equals(other.locale)) && Objects.equals(locale,other.locale)
|| (locale == null && other.locale == null))
&& Arrays.equals(offsets,other.offsets) && Arrays.equals(offsets,other.offsets)
&& Arrays.equals(argumentNumbers,other.argumentNumbers) && Arrays.equals(argumentNumbers,other.argumentNumbers)
&& Arrays.equals(formats,other.formats)); && Arrays.equals(formats,other.formats));
@ -1150,6 +1151,7 @@ public class MessageFormat extends Format {
/** /**
* Generates a hash code for the message format object. * Generates a hash code for the message format object.
*/ */
@Override
public int hashCode() { public int hashCode() {
return pattern.hashCode(); // enough for reasonable distribution return pattern.hashCode(); // enough for reasonable distribution
} }

View File

@ -711,13 +711,10 @@ public abstract class NumberFormat extends Format {
*/ */
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) { if (this == obj) {
return true; return true;
} }
if (getClass() != obj.getClass()) { if (obj == null || getClass() != obj.getClass()) {
return false; return false;
} }
NumberFormat other = (NumberFormat) obj; NumberFormat other = (NumberFormat) obj;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -122,18 +122,17 @@ public class ParsePosition {
/** /**
* Overrides equals * Overrides equals
*/ */
@Override
public boolean equals(Object obj) public boolean equals(Object obj)
{ {
if (obj == null) return false; return obj instanceof ParsePosition other
if (!(obj instanceof ParsePosition other)) && index == other.index && errorIndex == other.errorIndex;
return false;
return (index == other.index && errorIndex == other.errorIndex);
} }
/** /**
* Returns a hash code for this ParsePosition. * {@return a hash code for this ParsePosition}
* @return a hash code value for this object
*/ */
@Override
public int hashCode() { public int hashCode() {
return (errorIndex << 16) | index; return (errorIndex << 16) | index;
} }

View File

@ -729,9 +729,9 @@ public class RuleBasedCollator extends Collator{
* @return true if the current table-based collation object is the same * @return true if the current table-based collation object is the same
* as the table-based collation object obj; false otherwise. * as the table-based collation object obj; false otherwise.
*/ */
@Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj == null) return false; if (!super.equals(obj)) return false; // super does null and class checks
if (!super.equals(obj)) return false; // super does class check
RuleBasedCollator other = (RuleBasedCollator) obj; RuleBasedCollator other = (RuleBasedCollator) obj;
// all other non-transient information is also contained in rules. // all other non-transient information is also contained in rules.
return (getRules().equals(other.getRules())); return (getRules().equals(other.getRules()));
@ -740,6 +740,7 @@ public class RuleBasedCollator extends Collator{
/** /**
* Generates the hash code for the table-based collation object * Generates the hash code for the table-based collation object
*/ */
@Override
public int hashCode() { public int hashCode() {
return getRules().hashCode(); return getRules().hashCode();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -2409,9 +2409,7 @@ public class SimpleDateFormat extends DateFormat {
} }
/** /**
* Returns the hash code value for this {@code SimpleDateFormat} object. * {@return the hash code value for this {@code SimpleDateFormat} object}
*
* @return the hash code value for this {@code SimpleDateFormat} object.
*/ */
@Override @Override
public int hashCode() public int hashCode()
@ -2431,7 +2429,7 @@ public class SimpleDateFormat extends DateFormat {
public boolean equals(Object obj) public boolean equals(Object obj)
{ {
if (!super.equals(obj)) { if (!super.equals(obj)) {
return false; // super does class check return false; // super does null and class checks
} }
SimpleDateFormat that = (SimpleDateFormat) obj; SimpleDateFormat that = (SimpleDateFormat) obj;
return (pattern.equals(that.pattern) return (pattern.equals(that.pattern)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -91,10 +91,11 @@ public final class IntHashtable {
rehash(); rehash();
} }
@Override
public boolean equals (Object that) { public boolean equals (Object that) {
if (that.getClass() != this.getClass()) return false; if (!(that instanceof IntHashtable other)) {
return false;
IntHashtable other = (IntHashtable) that; }
if (other.size() != count || other.defaultValue != defaultValue) { if (other.size() != count || other.defaultValue != defaultValue) {
return false; return false;
} }
@ -106,6 +107,7 @@ public final class IntHashtable {
return true; return true;
} }
@Override
public int hashCode() { public int hashCode() {
// NOTE: This function isn't actually used anywhere in this package, but it's here // NOTE: This function isn't actually used anywhere in this package, but it's here
// in case this class is ever used to make sure we uphold the invariants about // in case this class is ever used to make sure we uphold the invariants about

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -46,6 +46,8 @@ import java.text.BreakIterator;
import java.text.CharacterIterator; import java.text.CharacterIterator;
import java.text.StringCharacterIterator; import java.text.StringCharacterIterator;
import java.util.MissingResourceException; import java.util.MissingResourceException;
import java.util.Objects;
import sun.text.CompactByteArray; import sun.text.CompactByteArray;
import sun.text.SupplementaryCharacterData; import sun.text.SupplementaryCharacterData;
@ -498,24 +500,9 @@ public class RuleBasedBreakIterator extends BreakIterator {
*/ */
@Override @Override
public boolean equals(Object that) { public boolean equals(Object that) {
try { return that instanceof RuleBasedBreakIterator other
if (that == null) { && checksum == other.checksum
return false; && Objects.equals(text, other.text);
}
RuleBasedBreakIterator other = (RuleBasedBreakIterator) that;
if (checksum != other.checksum) {
return false;
}
if (text == null) {
return other.text == null;
} else {
return text.equals(other.text);
}
}
catch(ClassCastException e) {
return false;
}
} }
/** /**
@ -527,8 +514,7 @@ public class RuleBasedBreakIterator extends BreakIterator {
} }
/** /**
* Compute a hashcode for this BreakIterator * {@return hashcode for this BreakIterator}
* @return A hash code
*/ */
@Override @Override
public int hashCode() { public int hashCode() {