[records] equality on float / double components
guy.steele at oracle.com
Wed Dec 6 18:10:07 UTC 2017
> On Dec 6, 2017, at 1:07 PM, Brian Goetz <brian.goetz at oracle.com> wrote:
> It's time to play everyone's favorite game show, "What about NaN".
> If we have a record:
> record Foo(float f);
> We would like Object.equals() to be reflexive, symmetric, and transitive. But if we define equals() in the obvious way (delegating to float==), then `new Foo(Float.NaN`) would not be equal to itself.
> If we delegate instead to `Float.compare(this.f, that.f)`, the NaN problem goes away (though comparison becomes modestly more expensive), but now +0 and -0 are distinguished (== treats them the same.)
This second choice (using FLoat.compare) is, IMHO, the correct one because it is consistent with the definition of Float.equals() (which goes back to JLS1), which was defined that way precisely because it “allows hash tables to operate properly” (because it is an equivalence relation).
If users want the behavior of `==` on, say, Point objects, then let them Do The Right Thing by providing an overloading of `==` for Point objects. (Oh, wait, ahem, cough, cough . . . :-)
P.S. The JDK8 documentation at https://docs.oracle.com/javase/8/docs/api/java/lang/Float.html#compare-float-float- <https://docs.oracle.com/javase/8/docs/api/java/lang/Float.html#compare-float-float-> has this INCORRECT summary of the return value for compareTo(Float) and compare(float,float):
the value 0 if anotherFloat is numerically equal to this Float; a value less than 0 if this Float is numerically less than anotherFloat; and a value greater than 0 if this Float is numerically greater thananotherFloat.
The more detailed descriptions speak the truth, but these summaries are in themselves incorrect and should be rewritten. The terms “numerically equal (less, greater)” do not apply to these comparisons in all cases.
More information about the amber-spec-observers