为何JDK中HashMap的values()方法空值处理逻辑设计得较为复杂?
values() method use a temporary variable? I'm reading the JDK source code and noticed the implementation of the
values()method in theHashMapclass:public Collection<V> values() { Collection<V> vs = values; if (vs == null) { vs = new Values(); values = vs; } return vs; }But I think it can be simplified to a more concise logic:
public Collection<V> values() { if (values == null) { values = new Values(); } return values; }I believe this complex design must have a reason, so I'm asking for an explanation.
Great question! At first glance, these two implementations seem functionally identical, but there are two key rationales behind the JDK team's choice:
1. Guarding against inconsistent reads in concurrent contexts
Even though HashMap is not thread-safe (and its documentation clearly states this), real-world code sometimes ends up using it in multi-threaded environments by accident. The temporary variable vs ensures we only read the values instance field once at the start of the method.
Without this local variable, if another thread modifies the values field between the if (values == null) check and the return values statement, you could end up returning a completely different instance than the one you just initialized—or even a null in edge cases. Using vs locks in the reference we're working with, making the method's behavior consistent for the current thread's execution path.
2. Micro-optimization for better performance
Accessing local variables is faster than accessing instance fields. Local variables live on the stack, which has faster access times, while instance fields require dereferencing the object's pointer to reach data on the heap. By reading values into vs once, we avoid potentially multiple heap accesses (your simplified version would read values twice: once for the check, once for the return).
While this gain is minuscule for a single call, core JDK classes are optimized to the extreme—every tiny improvement accumulates when methods like values() are invoked millions of times across countless applications.
It's easy to write this off as unnecessary complexity, but these small details reflect the careful engineering that goes into making Java's core libraries robust and performant.
内容的提问来源于stack exchange,提问作者Trần Kim Dự

