8261123: Augment discussion of equivalence classes in Object.equals and comparison methods
Reviewed-by: bpb, smarks, rriggs
This commit is contained in:
parent
2677f6f47d
commit
d547e1a847
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -62,11 +62,15 @@ import java.util.*;
|
||||
* because {@code a} and {@code b} are equivalent from the sorted set's
|
||||
* perspective.<p>
|
||||
*
|
||||
* Virtually all Java core classes that implement {@code Comparable} have natural
|
||||
* orderings that are consistent with equals. One exception is
|
||||
* {@code java.math.BigDecimal}, whose natural ordering equates
|
||||
* {@code BigDecimal} objects with equal values and different precisions
|
||||
* (such as 4.0 and 4.00).<p>
|
||||
* Virtually all Java core classes that implement {@code Comparable}
|
||||
* have natural orderings that are consistent with equals. One
|
||||
* exception is {@link java.math.BigDecimal}, whose {@linkplain
|
||||
* java.math.BigDecimal#compareTo natural ordering} equates {@code
|
||||
* BigDecimal} objects with equal numerical values and different
|
||||
* representations (such as 4.0 and 4.00). For {@link
|
||||
* java.math.BigDecimal#equals BigDecimal.equals()} to return true,
|
||||
* the representation and numerical value of the two {@code
|
||||
* BigDecimal} objects must be the same.<p>
|
||||
*
|
||||
* For the mathematically inclined, the <i>relation</i> that defines
|
||||
* the natural ordering on a given class C is:<pre>{@code
|
||||
@ -83,7 +87,12 @@ import java.util.*;
|
||||
* the class's {@link Object#equals(Object) equals(Object)} method:<pre>
|
||||
* {(x, y) such that x.equals(y)}. </pre><p>
|
||||
*
|
||||
* This interface is a member of the
|
||||
* In other words, when a class's natural ordering is consistent with
|
||||
* equals, the equivalence classes defined by the equivalence relation
|
||||
* of the {@code equals} method and the equivalence classes defined by
|
||||
* the quotient of the {@code compareTo} method are the same.
|
||||
*
|
||||
* <p>This interface is a member of the
|
||||
* <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
@ -99,33 +108,28 @@ public interface Comparable<T> {
|
||||
* negative integer, zero, or a positive integer as this object is less
|
||||
* than, equal to, or greater than the specified object.
|
||||
*
|
||||
* <p>The implementor must ensure
|
||||
* {@code sgn(x.compareTo(y)) == -sgn(y.compareTo(x))}
|
||||
* for all {@code x} and {@code y}. (This
|
||||
* implies that {@code x.compareTo(y)} must throw an exception iff
|
||||
* {@code y.compareTo(x)} throws an exception.)
|
||||
* <p>The implementor must ensure {@link Integer#signum
|
||||
* signum}{@code (x.compareTo(y)) == -signum(y.compareTo(x))} for
|
||||
* all {@code x} and {@code y}. (This implies that {@code
|
||||
* x.compareTo(y)} must throw an exception if and only if {@code
|
||||
* y.compareTo(x)} throws an exception.)
|
||||
*
|
||||
* <p>The implementor must also ensure that the relation is transitive:
|
||||
* {@code (x.compareTo(y) > 0 && y.compareTo(z) > 0)} implies
|
||||
* {@code x.compareTo(z) > 0}.
|
||||
*
|
||||
* <p>Finally, the implementor must ensure that {@code x.compareTo(y)==0}
|
||||
* implies that {@code sgn(x.compareTo(z)) == sgn(y.compareTo(z))}, for
|
||||
* all {@code z}.
|
||||
* <p>Finally, the implementor must ensure that {@code
|
||||
* x.compareTo(y)==0} implies that {@code signum(x.compareTo(z))
|
||||
* == signum(y.compareTo(z))}, for all {@code z}.
|
||||
*
|
||||
* <p>It is strongly recommended, but <i>not</i> strictly required that
|
||||
* @apiNote
|
||||
* It is strongly recommended, but <i>not</i> strictly required that
|
||||
* {@code (x.compareTo(y)==0) == (x.equals(y))}. Generally speaking, any
|
||||
* class that implements the {@code Comparable} interface and violates
|
||||
* this condition should clearly indicate this fact. The recommended
|
||||
* language is "Note: this class has a natural ordering that is
|
||||
* inconsistent with equals."
|
||||
*
|
||||
* <p>In the foregoing description, the notation
|
||||
* {@code sgn(}<i>expression</i>{@code )} designates the mathematical
|
||||
* <i>signum</i> function, which is defined to return one of {@code -1},
|
||||
* {@code 0}, or {@code 1} according to whether the value of
|
||||
* <i>expression</i> is negative, zero, or positive, respectively.
|
||||
*
|
||||
* @param o the object to be compared.
|
||||
* @return a negative integer, zero, or a positive integer as this object
|
||||
* is less than, equal to, or greater than the specified object.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -78,15 +78,16 @@ public class Object {
|
||||
* used in {@code equals} comparisons on the object is modified.
|
||||
* This integer need not remain consistent from one execution of an
|
||||
* application to another execution of the same application.
|
||||
* <li>If two objects are equal according to the {@code equals(Object)}
|
||||
* method, then calling the {@code hashCode} method on each of
|
||||
* the two objects must produce the same integer result.
|
||||
* <li>If two objects are equal according to the {@link
|
||||
* equals(Object) equals} method, then calling the {@code
|
||||
* hashCode} method on each of the two objects must produce the
|
||||
* same integer result.
|
||||
* <li>It is <em>not</em> required that if two objects are unequal
|
||||
* according to the {@link java.lang.Object#equals(java.lang.Object)}
|
||||
* method, then calling the {@code hashCode} method on each of the
|
||||
* two objects must produce distinct integer results. However, the
|
||||
* programmer should be aware that producing distinct integer results
|
||||
* for unequal objects may improve the performance of hash tables.
|
||||
* according to the {@link equals(Object) equals} method, then
|
||||
* calling the {@code hashCode} method on each of the two objects
|
||||
* must produce distinct integer results. However, the programmer
|
||||
* should be aware that producing distinct integer results for
|
||||
* unequal objects may improve the performance of hash tables.
|
||||
* </ul>
|
||||
*
|
||||
* @implSpec
|
||||
@ -127,15 +128,27 @@ public class Object {
|
||||
* <li>For any non-null reference value {@code x},
|
||||
* {@code x.equals(null)} should return {@code false}.
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* An equivalence relation partitions the elements it operates on
|
||||
* into <i>equivalence classes</i>; all the members of an
|
||||
* equivalence class are equal to each other. Members of an
|
||||
* equivalence class are substitutable for each other, at least
|
||||
* for some purposes.
|
||||
*
|
||||
* @implSpec
|
||||
* The {@code equals} method for class {@code Object} implements
|
||||
* the most discriminating possible equivalence relation on objects;
|
||||
* that is, for any non-null reference values {@code x} and
|
||||
* {@code y}, this method returns {@code true} if and only
|
||||
* if {@code x} and {@code y} refer to the same object
|
||||
* ({@code x == y} has the value {@code true}).
|
||||
* <p>
|
||||
* Note that it is generally necessary to override the {@code hashCode}
|
||||
*
|
||||
* In other words, under the reference equality equivalence
|
||||
* relation, each equivalence class only has a single element.
|
||||
*
|
||||
* @apiNote
|
||||
* It is generally necessary to override the {@link hashCode hashCode}
|
||||
* method whenever this method is overridden, so as to maintain the
|
||||
* general contract for the {@code hashCode} method, which states
|
||||
* that equal objects must have equal hash codes.
|
||||
@ -183,7 +196,8 @@ public class Object {
|
||||
* primitive fields or references to immutable objects, then it is usually
|
||||
* the case that no fields in the object returned by {@code super.clone}
|
||||
* need to be modified.
|
||||
* <p>
|
||||
*
|
||||
* @implSpec
|
||||
* The method {@code clone} for class {@code Object} performs a
|
||||
* specific cloning operation. First, if the class of this object does
|
||||
* not implement the interface {@code Cloneable}, then a
|
||||
@ -214,13 +228,17 @@ public class Object {
|
||||
protected native Object clone() throws CloneNotSupportedException;
|
||||
|
||||
/**
|
||||
* Returns a string representation of the object. In general, the
|
||||
* Returns a string representation of the object.
|
||||
* @apiNote
|
||||
* In general, the
|
||||
* {@code toString} method returns a string that
|
||||
* "textually represents" this object. The result should
|
||||
* be a concise but informative representation that is easy for a
|
||||
* person to read.
|
||||
* It is recommended that all subclasses override this method.
|
||||
* <p>
|
||||
* The string output is not necessarily stable over time or across
|
||||
* JVM invocations.
|
||||
* @implSpec
|
||||
* The {@code toString} method for class {@code Object}
|
||||
* returns a string consisting of the name of the class of which the
|
||||
* object is an instance, the at-sign character `{@code @}', and
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -63,33 +63,38 @@ import java.util.Objects;
|
||||
* <p>When a {@code MathContext} object is supplied with a precision
|
||||
* setting of 0 (for example, {@link MathContext#UNLIMITED}),
|
||||
* arithmetic operations are exact, as are the arithmetic methods
|
||||
* which take no {@code MathContext} object. (This is the only
|
||||
* behavior that was supported in releases prior to 5.) As a
|
||||
* corollary of computing the exact result, the rounding mode setting
|
||||
* of a {@code MathContext} object with a precision setting of 0 is
|
||||
* not used and thus irrelevant. In the case of divide, the exact
|
||||
* quotient could have an infinitely long decimal expansion; for
|
||||
* example, 1 divided by 3. If the quotient has a nonterminating
|
||||
* decimal expansion and the operation is specified to return an exact
|
||||
* result, an {@code ArithmeticException} is thrown. Otherwise, the
|
||||
* exact result of the division is returned, as done for other
|
||||
* operations.
|
||||
* which take no {@code MathContext} object. As a corollary of
|
||||
* computing the exact result, the rounding mode setting of a {@code
|
||||
* MathContext} object with a precision setting of 0 is not used and
|
||||
* thus irrelevant. In the case of divide, the exact quotient could
|
||||
* have an infinitely long decimal expansion; for example, 1 divided
|
||||
* by 3. If the quotient has a nonterminating decimal expansion and
|
||||
* the operation is specified to return an exact result, an {@code
|
||||
* ArithmeticException} is thrown. Otherwise, the exact result of the
|
||||
* division is returned, as done for other operations.
|
||||
*
|
||||
* <p>When the precision setting is not 0, the rules of
|
||||
* {@code BigDecimal} arithmetic are broadly compatible with selected
|
||||
* modes of operation of the arithmetic defined in ANSI X3.274-1996
|
||||
* and ANSI X3.274-1996/AM 1-2000 (section 7.4). Unlike those
|
||||
* standards, {@code BigDecimal} includes many rounding modes, which
|
||||
* were mandatory for division in {@code BigDecimal} releases prior
|
||||
* to 5. Any conflicts between these ANSI standards and the
|
||||
* {@code BigDecimal} specification are resolved in favor of
|
||||
* {@code BigDecimal}.
|
||||
* <p>When the precision setting is not 0, the rules of {@code
|
||||
* BigDecimal} arithmetic are broadly compatible with selected modes
|
||||
* of operation of the arithmetic defined in ANSI X3.274-1996 and ANSI
|
||||
* X3.274-1996/AM 1-2000 (section 7.4). Unlike those standards,
|
||||
* {@code BigDecimal} includes many rounding modes. Any conflicts
|
||||
* between these ANSI standards and the {@code BigDecimal}
|
||||
* specification are resolved in favor of {@code BigDecimal}.
|
||||
*
|
||||
* <p>Since the same numerical value can have different
|
||||
* representations (with different scales), the rules of arithmetic
|
||||
* and rounding must specify both the numerical result and the scale
|
||||
* used in the result's representation.
|
||||
*
|
||||
* The different representations of the same numerical value are
|
||||
* called members of the same <i>cohort</i>. The {@linkplain
|
||||
* compareTo(BigDecimal) natural order} of {@code BigDecimal}
|
||||
* considers members of the same cohort to be equal to each other. In
|
||||
* contrast, the {@link equals equals} method requires both the
|
||||
* numerical value and representation to be the same for equality to
|
||||
* hold. The results of methods like {@link scale} and {@link
|
||||
* unscaledValue} will differ for numerically equal values with
|
||||
* different representations.
|
||||
*
|
||||
* <p>In general the rounding modes and precision setting determine
|
||||
* how operations return results with a limited number of digits when
|
||||
@ -3040,16 +3045,21 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
// Comparison Operations
|
||||
|
||||
/**
|
||||
* Compares this {@code BigDecimal} with the specified
|
||||
* Compares this {@code BigDecimal} numerically with the specified
|
||||
* {@code BigDecimal}. Two {@code BigDecimal} objects that are
|
||||
* equal in value but have a different scale (like 2.0 and 2.00)
|
||||
* are considered equal by this method. This method is provided
|
||||
* in preference to individual methods for each of the six boolean
|
||||
* comparison operators ({@literal <}, ==,
|
||||
* {@literal >}, {@literal >=}, !=, {@literal <=}). The
|
||||
* suggested idiom for performing these comparisons is:
|
||||
* {@code (x.compareTo(y)} <<i>op</i>> {@code 0)}, where
|
||||
* are considered equal by this method. Such values are in the
|
||||
* same <i>cohort</i>.
|
||||
*
|
||||
* This method is provided in preference to individual methods for
|
||||
* each of the six boolean comparison operators ({@literal <}, ==,
|
||||
* {@literal >}, {@literal >=}, !=, {@literal <=}). The suggested
|
||||
* idiom for performing these comparisons is: {@code
|
||||
* (x.compareTo(y)} <<i>op</i>> {@code 0)}, where
|
||||
* <<i>op</i>> is one of the six comparison operators.
|
||||
|
||||
* @apiNote
|
||||
* Note: this class has a natural ordering that is inconsistent with equals.
|
||||
*
|
||||
* @param val {@code BigDecimal} to which this {@code BigDecimal} is
|
||||
* to be compared.
|
||||
@ -3125,12 +3135,12 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this {@code BigDecimal} with the specified
|
||||
* {@code Object} for equality. Unlike {@link
|
||||
* #compareTo(BigDecimal) compareTo}, this method considers two
|
||||
* {@code BigDecimal} objects equal only if they are equal in
|
||||
* value and scale (thus 2.0 is not equal to 2.00 when compared by
|
||||
* this method).
|
||||
* Compares this {@code BigDecimal} with the specified {@code
|
||||
* Object} for equality. Unlike {@link #compareTo(BigDecimal)
|
||||
* compareTo}, this method considers two {@code BigDecimal}
|
||||
* objects equal only if they are equal in value and
|
||||
* scale. Therefore 2.0 is not equal to 2.00 when compared by this
|
||||
* method.
|
||||
*
|
||||
* @param x {@code Object} to which this {@code BigDecimal} is
|
||||
* to be compared.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -33,14 +33,16 @@ import java.util.function.ToDoubleFunction;
|
||||
import java.util.Comparators;
|
||||
|
||||
/**
|
||||
* A comparison function, which imposes a <i>total ordering</i> on some
|
||||
* collection of objects. Comparators can be passed to a sort method (such
|
||||
* as {@link Collections#sort(List,Comparator) Collections.sort} or {@link
|
||||
* Arrays#sort(Object[],Comparator) Arrays.sort}) to allow precise control
|
||||
* over the sort order. Comparators can also be used to control the order of
|
||||
* certain data structures (such as {@link SortedSet sorted sets} or {@link
|
||||
* SortedMap sorted maps}), or to provide an ordering for collections of
|
||||
* objects that don't have a {@link Comparable natural ordering}.<p>
|
||||
* A comparison function, which imposes a <i>total ordering</i> on
|
||||
* some collection of objects. Comparators can be passed to a sort
|
||||
* method (such as {@link Collections#sort(List,Comparator)
|
||||
* Collections.sort} or {@link Arrays#sort(Object[],Comparator)
|
||||
* Arrays.sort}) to allow precise control over the sort order.
|
||||
* Comparators can also be used to control the order of certain data
|
||||
* structures (such as {@linkplain SortedSet sorted sets} or
|
||||
* {@linkplain SortedMap sorted maps}), or to provide an ordering for
|
||||
* collections of objects that don't have a {@linkplain Comparable
|
||||
* natural ordering}.<p>
|
||||
*
|
||||
* The ordering imposed by a comparator {@code c} on a set of elements
|
||||
* {@code S} is said to be <i>consistent with equals</i> if and only if
|
||||
@ -89,6 +91,11 @@ import java.util.Comparators;
|
||||
* equals(Object)} method(s):<pre>
|
||||
* {(x, y) such that x.equals(y)}. </pre>
|
||||
*
|
||||
* In other words, when the imposed ordering is consistent with
|
||||
* equals, the equivalence classes defined by the equivalence relation
|
||||
* of the {@code equals} method and the equivalence classes defined by
|
||||
* the quotient of the {@code compare} method are the same.
|
||||
|
||||
* <p>Unlike {@code Comparable}, a comparator may optionally permit
|
||||
* comparison of null arguments, while maintaining the requirements for
|
||||
* an equivalence relation.
|
||||
@ -112,31 +119,27 @@ public interface Comparator<T> {
|
||||
* zero, or a positive integer as the first argument is less than, equal
|
||||
* to, or greater than the second.<p>
|
||||
*
|
||||
* The implementor must ensure that {@code sgn(compare(x, y)) ==
|
||||
* -sgn(compare(y, x))} for all {@code x} and {@code y}. (This
|
||||
* implies that {@code compare(x, y)} must throw an exception if and only
|
||||
* if {@code compare(y, x)} throws an exception.)<p>
|
||||
* The implementor must ensure that {@link Integer#signum
|
||||
* signum}{@code (compare(x, y)) == -signum(compare(y, x))} for
|
||||
* all {@code x} and {@code y}. (This implies that {@code
|
||||
* compare(x, y)} must throw an exception if and only if {@code
|
||||
* compare(y, x)} throws an exception.)<p>
|
||||
*
|
||||
* The implementor must also ensure that the relation is transitive:
|
||||
* {@code ((compare(x, y)>0) && (compare(y, z)>0))} implies
|
||||
* {@code compare(x, z)>0}.<p>
|
||||
*
|
||||
* Finally, the implementor must ensure that {@code compare(x, y)==0}
|
||||
* implies that {@code sgn(compare(x, z))==sgn(compare(y, z))} for all
|
||||
* {@code z}.<p>
|
||||
* Finally, the implementor must ensure that {@code compare(x,
|
||||
* y)==0} implies that {@code signum(compare(x,
|
||||
* z))==signum(compare(y, z))} for all {@code z}.<p>
|
||||
*
|
||||
* @apiNote
|
||||
* It is generally the case, but <i>not</i> strictly required that
|
||||
* {@code (compare(x, y)==0) == (x.equals(y))}. Generally speaking,
|
||||
* any comparator that violates this condition should clearly indicate
|
||||
* this fact. The recommended language is "Note: this comparator
|
||||
* imposes orderings that are inconsistent with equals."<p>
|
||||
*
|
||||
* In the foregoing description, the notation
|
||||
* {@code sgn(}<i>expression</i>{@code )} designates the mathematical
|
||||
* <i>signum</i> function, which is defined to return one of {@code -1},
|
||||
* {@code 0}, or {@code 1} according to whether the value of
|
||||
* <i>expression</i> is negative, zero, or positive, respectively.
|
||||
*
|
||||
* @param o1 the first object to be compared.
|
||||
* @param o2 the second object to be compared.
|
||||
* @return a negative integer, zero, or a positive integer as the
|
||||
@ -150,13 +153,14 @@ public interface Comparator<T> {
|
||||
int compare(T o1, T o2);
|
||||
|
||||
/**
|
||||
* Indicates whether some other object is "equal to" this
|
||||
* comparator. This method must obey the general contract of
|
||||
* {@link Object#equals(Object)}. Additionally, this method can return
|
||||
* {@code true} <i>only</i> if the specified object is also a comparator
|
||||
* and it imposes the same ordering as this comparator. Thus,
|
||||
* {@code comp1.equals(comp2)} implies that {@code sgn(comp1.compare(o1,
|
||||
* o2))==sgn(comp2.compare(o1, o2))} for every object reference
|
||||
* Indicates whether some other object is "equal to"
|
||||
* this comparator. This method must obey the general contract of
|
||||
* {@link Object#equals(Object)}. Additionally, this method can
|
||||
* return {@code true} <i>only</i> if the specified object is also
|
||||
* a comparator and it imposes the same ordering as this
|
||||
* comparator. Thus, {@code comp1.equals(comp2)} implies that
|
||||
* {@link Integer#signum signum}{@code (comp1.compare(o1,
|
||||
* o2))==signum(comp2.compare(o1, o2))} for every object reference
|
||||
* {@code o1} and {@code o2}.<p>
|
||||
*
|
||||
* Note that it is <i>always</i> safe <i>not</i> to override
|
||||
|
Loading…
Reference in New Issue
Block a user