Collection size expansion logic refactor in Java 18
In Java 18, the array expansion code has huge change compared to Java 8.
For Java 18 ArrayList
and PriorityQueue
, their array expansion calls ArraysSupport.newLength()
.
ArrayList
We only discuss the scenario of appending 1 element.
Let’s take a look of what inside the ArrayList
.
1 | // This is ArrayList's the simplest adding function, which aims to append the element |
The main responsibility of grow() is to expand the size of internal array elementData
.
1 | // When the outside wants to append 1 element, the grow() helper method will set the minCapacity = 1 |
Compared to Java 8, Java 18 removed ensureCapacityInternal()
, ensureExplicitCapacity()
and let grow()
to undertake more responsibility.
Previously ensureCapacityInternal()
is responsible for testing elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA
while ensureExplicitCapacity()
is responsible for some task of ArraysSupport.newLength()
.
Let’s take a look of what inside ArraysSupport
.
1 | // A soft maximum array length imposed by array growth computations. |
Java 18 considered the limitation of special Hotspot JVM by setting a SOFT_MAX
to Integer.MAX_VALUE - 8
rather than directly expand the internal array to Integer.MAX_VALUE
.
The whole internal array size growing during appending element one by one is clear:
- When
1 < size < 2/3 * SOFT_MAX
, theelementData
will add 1/2 size - When
2/3 * SOFT_MAX < size <= SOFT_MAX - 1
, adding1/2 * SOFT_MAX
may cause the wholeelementData.length
>Integer.MAX_VALUE
. So it extendselementData
toSOFT_MAX
directly. - When
SOFT_MAX - 1 < size
, just keep growing1
.- In most common case, we don’t store the Integer.MAX_VALUE amount of elements into one ArrayList
- This growing 1 operation may aim to delay the application crash.
PriorityQueue
1 | private void grow(int minCapacity) { |
The only difference of grow()
strategy between PriorityQueue
and ArrayList
is the preferred growth.
ArrayList
prefers expand half of its current capacity while PriorityQueue
prefers only grow 2 when less than 64
and grow half when big than 64.