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

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

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

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

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

8 ответов


нет, ensureCapacity не менять логические размере на ArrayList - это меняет емкости - размер списка может достигать до следующий должен скопировать значения.

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

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

EDIT: похоже, вы хотите своего рода 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);
    }
}

обеспечение емкости не добавляет элементы в список. Вы можете получить только элемент 190 или добавить в элемент 190, если вы уже добавили 191 элемент. "Емкость" - это просто количество объектов ArrayList can удерживайте, прежде чем ему нужно изменить размер своей внутренней структуры данных (массива). Если у ArrayList была getCapacity (), то сделайте следующее:

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

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


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

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

если вы хотите заменить элемент 190 с "тестом" do:

a.set(190, "test");

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

a.add(190, "test");

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

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


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

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

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

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

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


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


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

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

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


  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());
}