Java 6与Java 7中ArrayList容量增长机制的差异及变更原因
Great question! The shift from the old capacity growth formula ((oldCapacity * 3)/2 + 1) in Java 6 and earlier to the new one (oldCapacity + (oldCapacity >> 1)) in Java 7+ wasn't about fixing a critical bug—it was about refining performance, memory efficiency, and code clarity. Let's break down the key reasons:
1. Better Memory Utilization
The old formula added an extra +1 to the 1.5x growth, which created small, unnecessary capacity overhead in many cases. For example:
- Starting from the default 10, the old strategy gave
(10*3)/2 +1 = 16, while the new strategy gives10 + (10>>1) =15. - Over time, this extra
+1accumulates: the old sequence goes 10→16→25→38..., while the new goes 10→15→22→33....
The extra capacity from the +1 often went unused, wasting memory for no practical benefit. The new strategy sticks strictly to a 1.5x growth (using integer arithmetic), aligning capacity more closely with actual needs.
2. Simplified, More Intuitive Logic
The new formula uses a bit shift (oldCapacity >>1) to calculate half the current capacity, then adds it back to get 1.5x growth. This is more readable and directly expresses the intent of "growing by 50%".
In contrast, the old formula (oldCapacity *3)/2 +1 was a bit opaque—why the extra +1? It was likely a holdover from early Java versions, but it served no meaningful purpose once JDK developers re-evaluated the tradeoffs.
3. Minor Performance Improvements
While modern JVMs optimize arithmetic operations well, the bit shift in the new formula is a low-level operation that can be slightly faster than the multiply-divide combination in the old formula. Additionally, avoiding the extra +1 eliminates a trivial but unnecessary computation.
That said, this performance gain is minimal in most real-world scenarios—memory efficiency was the bigger driver.
4. No Critical Bugs in the Old Strategy
Importantly, the old growth formula wasn't broken or buggy. It still maintained the required amortized O(1) time complexity for add() operations, as specified in the Oracle documentation. The change was purely a refinement to make ArrayList more efficient and maintainable.
Final Note
As you observed, this change has no impact on basic ArrayList usage—you still get automatic resizing with constant amortized time for adds. The shift was just a thoughtful tweak by the JDK team to optimize memory and code clarity without breaking existing functionality.
内容的提问来源于stack exchange,提问作者IgrewupwithSlackware

