I was reading Java\'s ArrayList
source code and noticed some comparisons in if-statements.
In Java 7, the method grow(int) uses
if (newC
a < b
and a - b < 0
can mean two different things. Consider the following code:
int a = Integer.MAX_VALUE;
int b = Integer.MIN_VALUE;
if (a < b) {
System.out.println("a < b");
}
if (a - b < 0) {
System.out.println("a - b < 0");
}
When run, this will only print a - b < 0
. What happens is that a < b
is clearly false, but a - b
overflows and becomes -1
, which is negative.
Now, having said that, consider that the array has a length that is really close to Integer.MAX_VALUE
. The code in ArrayList
goes like this:
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
oldCapacity
is really close to Integer.MAX_VALUE
so newCapacity
(which is oldCapacity + 0.5 * oldCapacity
) might overflow and become Integer.MIN_VALUE
(i.e. negative). Then, subtracting minCapacity
underflows back into a positive number.
This check ensures that the if
is not executed. If the code were written as if (newCapacity < minCapacity)
, it would be true
in this case (since newCapacity
is negative) so the newCapacity
would be forced to minCapacity
regardless of the oldCapacity
.
This overflow case is handled by the next if. When newCapacity
has overflowed, this will be true
: MAX_ARRAY_SIZE
is defined as Integer.MAX_VALUE - 8
and Integer.MIN_VALUE - (Integer.MAX_VALUE - 8) > 0
is true
. The newCapacity
is therefore rightly handled: hugeCapacity
method returns MAX_ARRAY_SIZE
or Integer.MAX_VALUE
.
NB: this is what the // overflow-conscious code
comment in this method is saying.