java arraylist ensureCapacity не работает

#java #arraylist

#java #arraylist

Вопрос:

Либо я делаю это неправильно, либо я не понимаю, как работает этот метод.

 ArrayList<String> a = new ArrayList<String>();
a.ensureCapacity(200);
a.add(190,"test");
System.out.println(a.get(190).toString());
  

Я бы подумал, что ensureCapacity позволит мне вставить запись с индексом до этого значения. Есть ли другой способ сделать это?

Я получаю ошибку IndexOutOfBounds в третьей строке.

Ответ №1:

Нет, ensureCapacity не изменяет логический размер an ArrayList — он изменяет емкость, то есть размер, которого может достичь список, прежде чем ему потребуется скопировать значения.

Вы должны быть хорошо осведомлены о разнице между логическим размером (т. Е. Доступны все значения в диапазоне [0, size) , и добавление нового элемента добавит его в индекс size ) и емкостью, которая на самом деле является скорее деталью реализации — это размер резервного массива, используемого для хранения.

Вызов ensureCapacity должен иметь какое-либо значение только с точки зрения производительности (избегая чрезмерного копирования) — это не влияет на логическую модель того, что находится в списке, если вы понимаете, что я имею в виду.

РЕДАКТИРОВАТЬ: похоже, вам нужен какой ensureSize() -то метод, который может выглядеть примерно так:

 public static void ensureSize(ArrayList<?> list, int size) {
    // Prevent excessive copying while we're adding
    list.ensureCapacity(size);
    while (list.size() < size) {
        list.add(null);
    }
}
  

Комментарии:

1. Итак, это то, о чем я думал, основываясь на результатах, которые я видел… Но есть ли способ сделать то, что мне нужно сделать?

2. используйте массив, если вы действительно хотите иметь один элемент в позиции 190

3. Может быть, использовать другой класс, а не ArrayList?

4. Это правильно, ребята: Я исправил опечатку. Это, несомненно, вершина моей карьеры.

5. Мой парад закончился. Спасибо, Джон. Теперь мне нужно будет придумать, как рассказать своим детям 😉

Ответ №2:

Так что, как упоминали другие ensureCapacity , это не для этого. Похоже, вы хотите начать с ArrayList 200 нулей? Тогда это был бы самый простой способ сделать это:

 ArrayList<String> a = new ArrayList<String>(Arrays.asList( new String[200] ));
  

Затем, если вы хотите заменить элемент 190 на «test», выполните:

 a.set(190, "test");
  

Это отличается от

 a.add(190, "test");
  

который добавит «test» в индекс 190 и сдвинет остальные 9 элементов вверх, в результате чего получится список размером 201.

Если вы знаете, что у вас всегда будет 200 элементов, возможно, было бы лучше просто использовать массив.

Комментарии:

1. 1, но я просто вывел простой пример, который вызвал ту же ошибку по той же причине, что и в моей реальной ситуации. Спасибо.

Ответ №3:

Обеспечение емкости не добавляет элементы в список. Вы можете получить элемент 190 или добавить в элемент 190 только в том случае, если вы уже добавили 191 элемент. «Емкость» — это просто количество объектов, которые может содержать ArrayList, прежде чем ему потребуется изменить размер своей внутренней структуры данных (массива). Если у ArrayList был getCapacity(), то выполнение этого:

 ArrayList<String> a = new ArrayList<String>();
a.ensureCapacity(200);
System.out.println(a.size());
System.out.println(a.getCapacity());
  

выведет 0 и некоторое число, большее или равное 200, соответственно

Ответ №4:

ArrayList поддерживает свою емкость (размер внутреннего массива) отдельно от его размера (количества добавленных элементов), а метод ‘set’ зависит от индекса, уже присвоенного элементу. Нет способа установить размер. Если вам это нужно, вы можете добавить фиктивные элементы с помощью цикла:

 for (int i = 200; --i >= 0;) a.add(null);
  

Ответ №5:

Еще раз JavaDoc, чтобы прояснить ситуацию:

 Throws: IndexOutOfBoundsException 
    - if index is out of range (index < 0 || index > size()).
  

Обратите внимание, что size() возвращает количество элементов, которые в данный момент хранятся в списке.

Ответ №6:

ensureCapacity просто убедитесь, что емкость базового массива больше или равна аргументу. Это не изменяет размер ArrayList . Он не вносит никаких изменений, видимых через API, поэтому вы не заметите разницы, за исключением того, что, вероятно, пройдет больше времени, прежде ArrayList чем он изменит размер своего внутреннего массива.

Ответ №7:

Добавление 190 нулевых записей в ArrayList пахнет неправильным использованием структуры данных.

  1. Подумайте об использовании стандартного примитивного массива.

  2. Если вам требуется дженерики или вы хотите более эффективно использовать пространство, тогда подумайте SparseArray , или даже Map подобный a HashMap может подойти для ваших целей.

Ответ №8:

   public static void fillArrayList(ArrayList<String> arrayList, long size) {
    for (int i = 0; i < size   1; i  ) {
      arrayList.add(i,"-1");
    }
  }

public static void main(String[] args) throws Exception {
  ArrayList<String> a = new ArrayList<String>(10);
  fillArrayList(a, 190);
  a.add(190,"test");
  System.out.println(a.get(190).toString());
}