Java ArrayList IndexOutOfBoundsException, несмотря на предоставление начальной емкости
Когда я делаю
ArrayList<Integer> arr = new ArrayList<Integer>(10);
arr.set(0, 1);
Java дает мне
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.set(Unknown Source)
at HelloWorld.main(HelloWorld.java:13)
Есть ли простой способ, я могу предварительно зарезервировать размер ArrayList, а затем сразу же использовать индексы, как массивы?
Ответы
Ответ 1
Здесь источник из ArrayList
:
Конструктор:
public ArrayList(int initialCapacity)
{
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
this.elementData = new Object[initialCapacity];
}
Вы вызвали set(int, E)
:
public E set(int index, E element)
{
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
Set
вызывает rangeCheck(int)
:
private void rangeCheck(int index)
{
if (index >= size) {
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
}
Это может быть тонким, но когда вы вызываете конструктор, несмотря на инициализацию Object[]
, вы не инициализировали size
. Следовательно, из rangeCheck
вы получаете IndexOutOfBoundsException
, так как size
равно 0. Вместо использования set(int, E)
вы можете использовать add(E e)
(добавляет e
типа e
в конец списка, в вашем случае: add(1)
), и этого не произойдет. Или, если вам это подходит, вы можете инициализировать все элементы до 0, как это предлагается в другом ответе.
Ответ 2
Как насчет этого:
ArrayList<Integer> arr = new ArrayList<Integer>(Collections.nCopies(10, 0));
Это инициализирует arr с 10 нулями. Затем вы можете свободно использовать индексы сразу.
Ответ 3
Я считаю, что проблема в том, что, хотя вы предложили выделенное пространство записей в массиве, вы фактически не создали записи.
Что возвращает arr.size()
?
Я думаю, вам нужно использовать метод add (T).
Ответ 4
Программирование в сторону, то, что вы пытаетесь сделать здесь, нелогично.
Представьте себе пустую коробку с яйцом. Это более или менее то, что вы создали. Затем вы скажете супер-точный и раздражающий, который-то-то-что-то-вы-робот, чтобы заменить 0-е яйцо другим яйцом. Робот сообщает об ошибке. Зачем? Он не может заменить 0-е яйцо, потому что там нет яйца! Существует пространство, предназначенное для 10 яиц, но в нем нет яиц!
Ответ 5
Вы можете использовать arr.add(1)
, который добавит 1
в первую пустую ячейку, т.е. с индексом 0.
Или вы можете создать свой собственный список:
public static class PresetArrayList<E> extends ArrayList<E> {
private static final long serialVersionUID = 1L;
public PresetArrayList(int initialCapacity) {
super(initialCapacity);
addAll(Collections.nCopies(initialCapacity, (E) null));
}
}
Тогда:
List<Integer> list = new PresetArrayList<Integer>(5);
list.set(3, 1);
System.out.println(list);
Печать
[null, null, null, 1, null]
Ответ 6
Это не ответ на Java, а ответ структуры данных.
Вы путаете концепцию Capacity
с Count
(или Size
).
Емкость - это когда вы сообщаете списку о резервном/предварительном размещении нескольких слотов заранее (в этом случае ArrayList вы говорите ему, что он создает массив из 10) в своем внутреннее хранилище. Когда это произойдет, список все еще не имеет никаких элементов.
Размер (или граф) - это количество элементов, которое действительно имеет список. В вашем коде вы действительно не добавили ни одного элемента, поэтому заслуживает исключения IndexOutOfBoundException.
Ответ 7
Пока вы не можете делать то, что хотите с помощью arraylist, есть еще один вариант: Arrays.asList()
Ответ 8
Емкость используется для подготовки ArrayList
для расширения. Возьмите петлю
List<Integer> list = new ArrayList<>();
for(final int i = 0; i < 1024; ++i) {
list.add(i);
}
list
запускается с емкостью 10
. Поэтому он содержит новый Integer[10]
внутри. По мере добавления цикла в список целые числа добавляются к этому массиву. Когда массив заполняется и добавляется еще один номер, новый массив распределяется в два раза по размеру старого, а старые значения копируются в новые. Добавление элемента - это O (1) в лучшем случае и O (N) в худшем случае. Но добавление N элементов займет около 2*1024
отдельных заданий: амортизированное линейное время.
Емкость не размер. Если вы еще не добавили в список массивов, размер будет равен нулю, и попытка записи в третий элемент завершится с ошибкой.