-
Notifications
You must be signed in to change notification settings - Fork 28.6k
KeySet.hashCode depends on ordering of keys provided to constructor #38919
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
Comments
Oh, slightly more info as to why this matters. The |
Oh, my. OK, we'll have to do something to fix that (probably sort them when inserting, or just use a different data structure). |
By default the Set and Map types or via literals in dart preserve insertion order. To get an unordered set you'd have to explicitly use HashSet or HashMap |
Well, but would iteration order matter in a hash set? Or, even better, does |
Iteration order is the preserved insertion order for LinkedHashSet and LinkedHashMap (the defaults). Map/Sets in general are mutable and don't have a meaningful hashCode. |
One thought is to use a Edit: The class is called |
Do the key sets always contain 4 keys? |
No, at most 4 in the default constructor, but there's a |
I have a PR that fixes this. |
From the docs for "The iteration order of the set is not specified and depends on the hashcodes of the provided elements. However, the order is stable: multiple iterations over the same set produce the same order, as long as the set is not modified." This is perfect for this use case. |
What would happen if two hash codes collide? It may depend on the implementation of the map. I'm going to throw together a dartpad and see if I can break it. |
FWIW SplayTreeSet is as slow as molasses |
OK, it's a contrived example, but demonstrative. Using a It's difficult to say how this might happen in a real-world scenario, but it may very well be possible. Whether or not there's a collision of this kind is presumably based on the number of buckets the |
Just a suggestion. Might be useful just to get things into sorted order, and generating the hashCode up front. You can ditch it after that, since the set is immutable and the only check you need afterwards is set equality. |
Scratch that. After trying pretty hard to get a collision in a real-world situation, I couldn't do it. It's probably not a big deal. |
Yeah, that definitely won't happen with And if something does return false from |
If you read that carefully, you'll see it doesn't really say that. If they are equal, they must return the same hashCode, but it doesn't say anything about the behavior when they're unequal. That's why hash sets and maps rely on both hashCode and equality to determine membership. Thanks for the PR though. Appreciate it. |
My apologies, you're correct. In this case, |
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of |
Simple example:
It appears that the Set literal's iteration order is influenced by insertion order. See use of
hashList
inKeySet.hashCode
.cc @gspencergoog
The text was updated successfully, but these errors were encountered: