El martes 9 de marzo de 2010 a las 03:02, Kevin L. Stern escribió:
Hice una búsqueda rápida y parece que Java está basado en el complemento de dos. No obstante, permítame señalar que, en general, este tipo de código me preocupa, ya que espero que en algún momento alguien venga y haga exactamente lo que Dmytro sugirió; es decir, alguien cambiará:
if (a - b > 0)
a
if (a > b)
y toda la nave se hundirá. Personalmente, me gusta evitar las obscuridades, como hacer que el desbordamiento de enteros sea una base esencial para mi algoritmo, a menos que haya una buena razón para hacerlo. En general, preferiría evitar el desbordamiento por completo y hacer que el escenario de desbordamiento sea más explícito:
if (oldCapacity > RESIZE_OVERFLOW_THRESHOLD) {
// Do something
} else {
// Do something else
}
Es un buen punto.
En ArrayList
no podemos hacer esto (o al menos no es compatible), porque
ensureCapacity
es una API pública y efectivamente ya acepta números negativos como solicitudes de una capacidad positiva que no puede satisfacerse.
La API actual se usa así:
int newcount = count + len;
ensureCapacity(newcount);
Si desea evitar el desbordamiento, deberá cambiar a algo menos natural como
ensureCapacity(count, len);
int newcount = count + len;
De todos modos, mantengo el código consciente del desbordamiento, pero agrego más comentarios de advertencia y crea una gran variedad de "esquemas" para que
ArrayList
el código ahora se vea así:
/**
* Increases the capacity of this <tt>ArrayList</tt> instance, if
* necessary, to ensure that it can hold at least the number of elements
* specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
public void ensureCapacity(int minCapacity) {
modCount++;
// Overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
// Overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
private int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
Webrev regenerado.
Martín
if (newCapacity - minCapacity < 0)
mejor queif (newCapacity < minCapacity)
en términos de prevención de desbordamiento?