2012-02-10 2 views
4

Я знаю, что я не могу сохранить значение в индексе ArrayList, который еще не был использован, т. Е. Меньше размера. Другими словами, если myArrayList.size() является 5, а затем, если я пытаюсь сделатьJava: лучший способ сохранить произвольный индекс ArrayList

myArrayList.set(10, "Hello World") 

я получить из ошибки границ. Но мое приложение нуждается в этом. Существует ли более элегантный способ, кроме цикла хранения нуля в каждом из промежуточных слотов?

Он смотрит на меня, как:

  • Это поведение является одинаковым в Vector
  • Если мне нужно, чтобы иметь возможность произвольного доступа (т.е. элемент в позиции X), то мой выбор Vector и ArrayList.
  • Я мог бы использовать HashMap и использовать индекс как ключ, но это действительно неэффективно.

Так что же изящное решение того, что похоже на обычный случай. Мне должно быть что-то не хватает ...

+3

Почему вы говорите, что решение карты было бы действительно неэффективным? Насколько строги ваши требования к пространству? –

+0

Почему использование HashMap менее эффективно, чем то, что вы предлагаете с помощью ArrayList? –

+0

Кроме того, вы знаете заранее, что будет самым высоким индексом? –

ответ

4

Я мог бы использовать HashMap и использовать индекс как ключ, но это действительно неэффективно.

Зависит. Если индексы, которые вы используете, очень разрежены, лучше использовать карту. Если индексы, как правило, тесно связаны друг с другом, я думаю, что нет лучшего способа, чем заполнить его нулями. Просто написать функцию полезности для него, что вы можете использовать снова и снова вместо того, чтобы повторять цикл везде вам это нужно, что-то вроде этого:

private void padTo(List<?> list, int size) { 
    for (int i=list.size(); i<size; i++) 
     list.add(null); 
} 
+3

Рассмотрите возможность вызова 'list.ensureCapacity (size)' перед циклом, чтобы избежать ненужных перераспределений памяти. – Mersenne

+0

Обратите внимание, что securityCapacity (размер) фактически не заполняет массив - http://stackoverflow.com/questions/7688151/java-arraylist-ensurecapacity-not-working –

3

Вместо этого вы можете использовать Map<Integer, MyClass>. В частности, если вы используете HashMap, он также будет O(1) - хотя он будет медленнее, чем ArrayList.

1

Похоже, вы хотите регулярный массив:

  • Вы хотите случайный доступ
  • Вы хотите задать некоторые крупные размер
+0

Вы можете указать размер ArrayList – blank

+3

Не думайте так. Это начальная выделенная емкость, но в начале размер равен нулю. – pitosalas

+0

Обычный массив не является опцией, если элементы, хранящиеся в списке, являются общими. –

1

Если вы определенно должны использовать список, а не карту , тогда лучше всего вы переопределить методы добавления и набора arraylist, чтобы сначала поместить нуль в индексы раньше. Нет другого лучшего способа. IMO

3

Вы можете использовать TreeMap<key, value>, отсортированной в естественном порядке по value.

Здесь вы можете сохранить стоимость как индекс. Вы можете вставить любое значение, оно не должно быть в порядке. Это кажется самым простым решением.

+0

Подробнее об этом: https://github.com/ google/guava/wiki/UsingAndAvoidingNullExplained # specific-cases – Yar

1

HashMap, вероятно, гораздо менее эффективен, чем вы думаете, попробуйте. В противном случае я не могу думать об этом более элегантно, чем цикл и заполнение нулем. Если вы хотите хотя бы элегантности изложения, тогда вы всегда можете подклассифицировать ArrayList и добавить метод expandSet (position, value), чтобы скрыть все петли и тому подобное. Возможно, это не вариант? Если у вас не просто метод утилиты где-то еще, но это не так приятно imho, хотя он будет работать и с другими типами списков тоже, я думаю ...

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

0

Если вы ищете разреженный массив (где большинство индексов будет пустым), Карта какой-то (вероятно, HashMap) будет вашим лучшим выбором. Любое решение массива-экска будет вынуждено зарезервировать место для всех пустых индексов, что не очень эффективно с точки зрения пространства, а HashMap достаточно быстр для большинства обычных целей.

Если вы в конечном итоге заполните массив до некоторого n, вам нужно будет добавить нули в цикле, чтобы получить нужный вам индекс. Вы можете сделать это несколько более эффективным, предоставив ему начальную емкость количества элементов, которые вы в конечном итоге захотите сохранить (это не позволяет ArrayList изменять размер). new ArrayList(n) будет работать нормально. К сожалению, нет простого способа сделать его определенным размером для начала, за исключением добавления вещей в цикл, когда вы это сделаете.

+0

Я считаю, что настраивает «емкость» не «размер» – pitosalas

+0

@pitosalas Хороший улов. Фиксация сейчас. – Retief

Смежные вопросы