Em terça-feira, 9 de março de 2010 às 03:02, Kevin L. Stern escreveu:
Eu fiz uma pesquisa rápida e parece que o Java é de fato baseado em dois. No entanto, permita-me salientar que, em geral, esse tipo de código me preocupa, pois espero que em algum momento alguém venha e faça exatamente o que o Dmytro sugeriu; isto é, alguém mudará:
if (a - b > 0)
para
if (a > b)
e todo o navio afundará. Pessoalmente, gosto de evitar obscuridades, como tornar o número inteiro excedente uma base essencial para o meu algoritmo, a menos que haja uma boa razão para fazê-lo. Em geral, eu preferiria evitar o estouro por completo e tornar o cenário de estouro mais explícito:
if (oldCapacity > RESIZE_OVERFLOW_THRESHOLD) {
// Do something
} else {
// Do something else
}
É um bom argumento.
Em ArrayList
nós não podemos fazer isso (ou pelo menos não a compatibilidade), porque
ensureCapacity
é uma API pública e eficaz já aceita números negativos como os pedidos para uma capacidade positivo que não pode ser satisfeita.
A API atual é usada assim:
int newcount = count + len;
ensureCapacity(newcount);
Se você quiser evitar transbordamentos, precisará mudar para algo menos natural como
ensureCapacity(count, len);
int newcount = count + len;
De qualquer forma, estou mantendo o código com excesso de consciência, mas adicionando mais comentários de aviso e "delineando" a enorme criação de matriz para que
ArrayList
o código agora se pareça com:
/**
* 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.
Martin
if (newCapacity - minCapacity < 0)
melhor do queif (newCapacity < minCapacity)
em termos de prevenção de estouro?