Difference between if (a - b < 0) and if (a < b)

后端 未结 4 1621
北荒
北荒 2020-12-22 15:47

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         


        
4条回答
  •  生来不讨喜
    2020-12-22 15:50

    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.

提交回复
热议问题