Uh oh!
There was an error while loading. Please reload this page.
Add equals/hashCode consistent with compareTo for value-semantics Comparable classes - #1201
Merged
dr-jts merged 2 commits intoJun 17, 2026
Merged
Conversation
…parable classes (locationtech#1184) Several classes implement Comparable with a meaningful compareTo() but do not override equals(), so two objects ordered as equal (compareTo == 0) are not equal by equals(). Add equals() and hashCode() to the classes whose compareTo defines a genuine value equality, defining equals() as (compareTo == 0) so the relation holds by construction, with hashCode() over the same fields: - LinearLocation (componentIndex, segmentIndex, segmentFraction) - EdgeIntersection (segmentIndex, dist) - NodeSection (isA, dim, id, ringId, v0, v1) - OrientedCoordinateArray (points, walked in canonical orientation order so an array and its reverse hash equally) The remaining Comparable classes (BoundablePair, EdgeEnd, Corner, SweepLineEvent, OffsetCurveSection, ...) use compareTo as a sort or priority ordering keyed on a subset of state, where compareTo == 0 does not imply object identity; aligning equals there would conflate distinct objects, so they are intentionally left unchanged (as the Comparable contract permits). Add consistency tests for the updated classes. Update history. Fixeslocationtech#1184 Co-authored-by: Claude <noreply@anthropic.com>
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 28, 2026
bjornharrtell pushed a commit
to bjornharrtell/jts
that referenced
this pull request
Aug 31, 2026
…ontech#1228) compareTo() used raw </> comparisons on segmentFraction/dist, which are always false for NaN and made compareTo (and thus equals(), added in locationtech#1201) fall through to 0 whenever NaN was compared to any other value on the same segment/index. This broke transitivity of equals() and its consistency with hashCode(). Use Double.compare() instead, matching Double's NaN ordering semantics already used by hashCode().
bjornharrtell added a commit
to bjornharrtell/jts
that referenced
this pull request
Aug 31, 2026
…ontech#1228) compareTo() used raw </> comparisons on segmentFraction/dist, which are always false for NaN and made compareTo (and thus equals(), added in locationtech#1201) fall through to 0 whenever NaN was compared to any other value on the same segment/index. This broke transitivity of equals() and its consistency with hashCode(). Use Double.compare() instead, matching Double's NaN ordering semantics already used by hashCode().
bjornharrtell added a commit
to bjornharrtell/jts
that referenced
this pull request
Aug 31, 2026
…ontech#1228) compareTo() used raw </> comparisons on segmentFraction/dist, which are always false for NaN and made compareTo (and thus equals(), added in locationtech#1201) fall through to 0 whenever NaN was compared to any other value on the same segment/index. This broke transitivity of equals() and its consistency with hashCode(). Use Double.compare() instead, matching Double's NaN ordering semantics already used by hashCode().
bjornharrtell added a commit
to bjornharrtell/jts
that referenced
this pull request
Aug 31, 2026
compareTo() used raw </> comparisons on segmentFraction/dist, which are always false for NaN and made compareTo (and thus equals(), added in locationtech#1201) fall through to 0 whenever NaN was compared to any other value on the same segment/index. This broke transitivity of equals() and its consistency with hashCode(). Use Double.compare() instead, matching Double's NaN ordering semantics already used by hashCode().
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Several JTS classes implement
Comparablewith a meaningfulcompareTo()but do not overrideequals(), so two objects thatcompareTo()orders as equal (returns 0) are not equal byequals(). This violates the recommended consistency betweencompareToandequals, and means the affected types misbehave as keys in hash-based collections.Add
equals()andhashCode()to the classes whosecompareTodefines a genuine value equality, definingequals()as(compareTo == 0)so the relation holds by construction, withhashCode()over the same fields.Changes Made:
LinearLocation—(componentIndex, segmentIndex, segmentFraction).EdgeIntersection—(segmentIndex, dist).NodeSection—(isA, dim, id, ringId, v0, v1).OrientedCoordinateArray— points walked in canonical orientation order, so an array and its reverse (which compare equal) hash equally.OrientedCoordinateArray).The remaining
Comparableclasses (BoundablePair,EdgeEnd,Corner,SweepLineEvent,OffsetCurveSection, …) usecompareToas a sort or priority ordering keyed on a subset of state, wherecompareTo == 0does not imply object identity (e.g.BoundablePairorders by distance only). Aligningequalsthere would conflate distinct objects, so they are intentionally left unchanged, as theComparablecontract permits.Fixes#1184