В четверг, 9 марта 2010 года в 03:02 Кевин Л. Стерн написал:
Я сделал быстрый поиск, и оказалось, что Java действительно основана на двух дополнениях. Тем не менее, пожалуйста, позвольте мне указать, что в целом этот тип кода беспокоит меня, так как я полностью ожидаю, что в какой-то момент кто-то придет и сделает именно то, что предложил Дмитрий; то есть кто-то изменится
if (a - b > 0)
в
if (a > b)
и весь корабль утонет. Лично мне нравится избегать неясностей, таких как целочисленное переполнение, являющихся важной основой для моего алгоритма, если для этого нет веских оснований. В общем, я бы предпочел вообще избежать переполнения и сделать сценарий переполнения более явным:
if (oldCapacity > RESIZE_OVERFLOW_THRESHOLD) {
// Do something
} else {
// Do something else
}
Это хороший момент.
В ArrayList
мы не можем сделать это (или , по крайней мере , не совместимо), поскольку
ensureCapacity
является публичной API и эффективно уже принимает отрицательные числа как запросы положительного потенциала , который не может быть удовлетворен.
Текущий API используется следующим образом:
int newcount = count + len;
ensureCapacity(newcount);
Если вы хотите избежать переполнения, вам нужно перейти на что-то менее естественное, например,
ensureCapacity(count, len);
int newcount = count + len;
Как бы то ни было, я сохраняю код с переполнением, но добавляю больше предупреждающих комментариев и «выделяю» создание огромного массива так, чтобы
ArrayList
код теперь выглядел следующим образом:
/**
* 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;
}
Вебрев восстановлен.
Мартин
if (newCapacity - minCapacity < 0)
лучше, чемif (newCapacity < minCapacity)
с точки зрения предотвращения переполнения?