-
Notifications
You must be signed in to change notification settings - Fork 3k
Core: Lazily compute & cache hashCode in CharSequenceWrapper #10023
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
Conversation
| @Override | ||
| public int hashCode() { | ||
| return JavaHashes.hashCode(wrapped); | ||
| int hash = hashCode; |
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.
this uses a local hash var on purpose due to https://jeremymanson.blogspot.com/2008/12/benign-data-races-in-java.html. Also the String class itself uses the same approach when lazily calculating and caching a hashCode
| private JavaHashes() {} | ||
|
|
||
| public static int hashCode(CharSequence str) { | ||
| if (null == str) { |
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.
there are places in the codebase that use CharSequenceWrapper.wrap(...) and then set the wrapper to null. The issue was never uncovered because equals/hashCode was never called on those CharSequenceWrapper instances.
When adding TestCharSequenceWrapper I noticed that this failed with a NPE, so I fixed this here and also added some tests around this
| public class TestCharSequenceWrapper { | ||
|
|
||
| @Test | ||
| public void nullWrapper() { |
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.
this test uncovered a NPE in JavaHashes
|
|
||
| private CharSequence wrapped; | ||
| // lazily computed & cached hashCode | ||
| private transient int hashCode = 0; |
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.
Hmm, I'm not sure I'd set a default value of 0, since that technically can be a legit hashCode value for some series of characters no?
I think I'd make this an Integer hashCode and have it be null to identify that nothing is cached yet.
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.
But good call making it transient, that's important since it shouldn't be serialized and the cache somehow used across JVMs
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.
I went down this rabbit hole: https://stackoverflow.com/questions/18746394/can-a-non-empty-string-have-a-hashcode-of-zero
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.
ah good point, thanks for finding that. Instead of making this an Integer I actually introduced a boolean flag. The String implementation does the same thing so that the hash isn't re-calculated when the hash is actually 0
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.
Awesome, maybe just comment in the code that we're following what java.lang.String does
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.
good point, I've added a comment mentioning that this follows java.lang.String
93fe63f to
3eb4bf4
Compare
amogh-jahagirdar
left a comment
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.
This looks great to me!
|
|
||
| private CharSequence wrapped; | ||
| // lazily computed & cached hashCode | ||
| private transient int hashCode = 0; |
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.
Awesome, maybe just comment in the code that we're following what java.lang.String does
3eb4bf4 to
ba1127d
Compare
No description provided.