У меня есть проблема с ArrayList
. Мне нужен он для хранения результата. Поскольку я хочу запуститься с элемента n, я пытался дать ArrayList
способность с ensureCapacity(n+1)
использовать set(n,x)
но я добираюсь IndexOutOfBoundsException
.
Я пытался сохранить n add(x)
перед использованием набора и это работает.
Таким образом, я хотел бы знать, почему это не работает над моим путем и как решить это потому что помещенные n времена a add(x)
не хороший стиль ;-)
Если вам не нравится использовать собственный цикл и метод list add
напрямую, то есть другой способ. Создайте свой ArrayList
с нужным количеством элементов, например:
final int MAX_ELEMENTS = 1000;
List<Integer> myList = new ArrayList<Integer>(
Collections.<Integer>nCopies(MAX_ELEMENTS, null));
Или, если у вас уже есть список, размер которого вы хотите увеличить на n
элементов:
myList.addAll(Collections.<Integer>nCopies(n, null));
(Обратите внимание, здесь я предполагал, что список будет содержать объекты Integer
, но вы можете изменить его на свой собственный тип. Если вы работаете с типами raw / pre-Java 5, просто отбросьте общий декларации.)
Что касается вашего фактического вопроса: емкость! = содержимое. ArrayList внутренне имеет как физический массив, так и счетчик того, что на самом деле находится в нем. При увеличении емкости внутренний массив изменяется таким образом, что он может содержать такое количество элементов, однако счетчик не изменяется. Вам нужно добавить элементы, чтобы увеличить это количество.
С другой стороны, если вы просто пытаетесь установить определенные элементы и знаете максимум, который вы хотите использовать, почему бы не использовать массив напрямую? Если затем вам нужно передать этот массив в API, который принимает List
s, используйте Arrays.asList
. Другие классы по-прежнему могут изменять содержимое вашего резервного массива, но они не смогут увеличить его размер или емкость.
Когда вы изменяете емкость списка ArrayList, он не создает никаких элементов, он просто резервирует память, в которой могут быть элементы. Вы можете проверить размер до и после изменения емкости и увидите, что он не меняется.
Цель изменения емкости - если вы заранее знаете, сколько элементов у вас будет, то вы можете избежать ненужного повторного изменения размера при добавлении новых элементов и избежать потерь памяти из-за избытка неиспользуемой емкости.
Вы получаете это исключение, потому что sureCapacity () только проверяет, достаточно ли выделенной памяти для добавления объектов в ArrayList, я Поверьте, это на тот случай, если вы хотите добавить сразу несколько объектов без необходимости перемещать память.
Чтобы сделать то, что вы хотите, вам нужно сначала запустить ArrayList с нулевыми элементами ...
int n = 10; //capacity required
ArrayList foo = new ArrayList();
for( int i=0; i<=n; i++ ) {
foo.add(null);
}
Затем у вас есть объекты в списке, на которые вы можете ссылаться через индекс, и вы не получите исключение.
sureCapacity ()
имеет другое назначение. Его следует использовать в случаях, когда вы узнаете требуемый размер Списка
после его создания. Если вы знаете размер до того, как он станет конструктором, просто передайте его в качестве аргумента конструктору.
В первом случае используйте sureCapacity ()
, чтобы сохранить многократное копирование резервного массива при каждом добавлении. Однако при использовании этого метода структура остается в кажущемся несогласованным состоянии
size
в ArrayList
нет. Это, однако, нормально, поскольку емкость! = Размер
Используйте метод add (..)
, который является единственным методом увеличения размера .
поле:
ArrayList list = new ArrayList();
list.ensureCapacity(5); // this can be done with constructing new ArrayList(5)
for (int i = 0; i < list.size - 1; i ++) {
list.add(null);
}
list.add(yourObject);
Возможно, вам стоит переосмыслить выбор использования List
. Возможно, что Map
будет более подходящим, если элементы должны быть добавлены в нечетном порядке.
Уместно ли это, зависит от знаний о вашем использовании, которых у меня пока нет.
Будет ли структура данных в конечном итоге заполнена полностью или данные будут скудными?
Как уже ответили другие, sureCapacity ()
просто связано с производительностью, не часто используется обычным пользователем.
Из книги Брюса Экеля «Мышление на Java» :
В личном сообщении Джошуа Блох написал: «... Я считаю, что мы ошиблись, разрешив детали реализации (такие как размер хеш-таблицы и коэффициент загрузки) в наши API. Клиент должен , возможно, сообщить нам максимальный ожидаемый размер коллекции, и мы должны взять его оттуда. Клиенты могут легко принести больше вреда, чем пользы, выбрав значения для этих параметров. В качестве крайнего примера рассмотрим capacityIncrement. Никто никогда не должен устанавливать это, и мы не должны были предоставлять его. Если вы установите любое ненулевое значение, асимптотическая стоимость последовательности добавлений переходит от линейной к квадратичной. Другими словами, она снижает вашу производительность. Со временем мы начинаем подумайте об этом . Если вы посмотрите на IdentityHashMap, вы увидите, что он не имеет параметров настройки нижнего уровня »
то, что другие люди говорили о ensureCapacity() ...
вы должны написать класс типа DynamicArrayList extends ArrayList. затем просто переопределить add(n,x), чтобы сделать с логикой for loop add(null), о которой говорилось.