Core: Lazily compute & cache hashCode in CharSequenceWrapper#10023
Conversation
| @Override | ||
| public int hashCode() { | ||
| return JavaHashes.hashCode(wrapped); | ||
| int hash = hashCode; |
There was a problem hiding this comment.
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.
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.
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.
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.
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.
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.
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.
Awesome, maybe just comment in the code that we're following what java.lang.String does
There was a problem hiding this comment.
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.
This looks great to me!
|
|
||
| private CharSequence wrapped; | ||
| // lazily computed & cached hashCode | ||
| private transient int hashCode = 0; |
There was a problem hiding this comment.
Awesome, maybe just comment in the code that we're following what java.lang.String does
3eb4bf4 to
ba1127d
Compare
No description provided.