Подтвердить что ты не робот

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, а затем сразу же использовать индексы, как массивы?

4b9b3361

Ответ 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 отдельных заданий: амортизированное линейное время.

Емкость не размер. Если вы еще не добавили в список массивов, размер будет равен нулю, и попытка записи в третий элемент завершится с ошибкой.