-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BuiltList
won't compute hash as part of ==
.
#269
base: master
Are you sure you want to change the base?
Conversation
The implementation of `BuiltList.operator==` used `this.hashCode != other.hashCode` as a short-cut in operator `==`. However, computing `hashCode` can be as expensive as doing equality, since it has to visit all the same objects (otherwise the hash code won't be consistent with equality) and do a computation on each. This change makes the `hashCode` only be used if it's already computed by both `this` and `other`, in which case it should be free. It's a change in performance-behavior. A single `==` won't do double work, but repeated `==`s on the same objects might have been more efficient if the hash code was computed eagerly. For elements in a set or map, the hash code will be computed anyway, so it should not affect those. Having a list of `BuiltList`s and doing repeated `indexOf` with the same values on the list might suffer. I believe the trade-off is worth it, because most lists are not compared for equality, and those that are, are either one-off comparisons, or used as map keys or set elements.
other._hashCode != null && | ||
_hashCode != other._hashCode) { | ||
return false; | ||
} | ||
for (var i = 0; i != length; ++i) { | ||
if (other[i] != this[i]) return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For curiosity: This is the opposite order of what the platform collections otherwise use. For example. contains will use this[i] == needle
as a test, not the other way around.
Is there a reason this is not this[i] == other[i]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No reason that I can remember :)
Thanks Lasse! The use case I had in mind when I wrote this was for
then I thought it might be a win if there is some caching of the list hash codes. It's not that the lists are expected to be large--rather that they may contain complex objects that don't cache their hash codes. But, this was just a guess, I didn't (and still don't) have data to back it up. I guess a primary use case for I thought about calculating a more robust hash to allow quickly returning "almost certainly true" but did not actually explore that option :) in the end we would need real data to know if it's worth it. Did you have any particular app/codebase in mind for this PR? If you have any real data that can be quite compelling against my lack of data ;) Thanks. |
No specific use, I just ended up in the method when doing a code review and wondered about the design. It seemed like overkill to check hash codes first, and then do equals afterwards anyway, precisely because the |
The implementation of
BuiltList.operator==
usedthis.hashCode != other.hashCode
as a short-cut in operator==
. However, computinghashCode
can be as expensive as doing equality, since it has to visit all the same objects (otherwise the hash code won't be consistent with equality) and do a computation on each.This change makes the
hashCode
only be used if it's already computed by boththis
andother
, in which case it should be free.It's a change in performance-behavior. A single
==
won't do double work, but repeated==
s on the same objects might have been more efficient if the hash code was computed eagerly. For elements in a set or map, the hash code will be computed anyway, so it should not affect those. Having a list ofBuiltList
s and doing repeatedindexOf
with the same values on the list might suffer.I believe the trade-off is worth it, because most lists are not compared for equality, and those that are, are either one-off comparisons, or used as map keys or set elements.
(But be free to disagree.)