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, theelementDatawill add 1/2 size - When
2/3 * SOFT_MAX < size <= SOFT_MAX - 1, adding1/2 * SOFT_MAXmay cause the wholeelementData.length>Integer.MAX_VALUE. So it extendselementDatatoSOFT_MAXdirectly. - 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.