Початковий розмір для ArrayList


257

Ви можете встановити початковий розмір для ArrayList, виконавши

ArrayList<Integer> arr=new ArrayList<Integer>(10);

Однак ви не можете цього зробити

arr.add(5, 10);

оскільки це спричиняє виняток поза межами.

У чому полягає користь встановлення початкового розміру, якщо ви не можете отримати доступ до виділеного вами місця?

Функція додавання визначена add(int index, Object element)так, що я не додаю в індекс 10.


52
Насправді, у документах не очевидно, що до списку потрібно додати щонайменше n елементів, перш ніж ви зможете отримати set/addпункт n-1 .
Сприйняття

5
Сприйняття: Я не знаю, чи це очевидно, але це вказано. Доводиться уважно читати JavaDoc. Побіжно: IndexOutOfBoundsException - якщо індекс виходить за межі діапазону (індекс <0 || індекс> = розмір ()).
Натікс

3
Гм, конструктор каже: "Конструює порожній список із заданою початковою ємністю". Приймаючи поняття порожній список, не може бути індекс 5. Але я згоден, що це може бути не видно на перший погляд ...
quaylar

12
Я думаю, що також справедливо сказати, що якщо ви ініціалізуєте масив до певного значення, ви будете вважати, що доступні індекси, нижчі за це значення, і це є ArrayList. Я особисто хотів би метод, який дозволив би мені встановити такий розмір, щоб я міг ставити речі за певними показниками. Цей метод, здається, відсутній.
Ендрю Вільд

1
Який numbskull створив колекції таким чином ?! Це змушує зайву роботу для паралельного інстанціонування структури з елементами змінної довжини (тобто ArrayList <String []>, де кожен масив може мати різну довжину). Якщо пам'ять вже виділена, тому список не потребує перерозподілу після додавання N елементів, ці індекси повинні бути безпосередньо доступними з самого початку. Ніхто з Oracle ніхто не дізнався цю схему після C / C ++, C #, Objective C та Swift ?!
patrickjp93

Відповіді:


387

Ви плутаєте розмір списку масиву з його ємністю:

  • розмір є кількість елементів у списку;
  • ємність , скільки елементів списку потенційно може вмістити без перерозподілити свої внутрішні структури.

Під час дзвінка new ArrayList<Integer>(10)ви встановлюєте початкову потужність списку , а не його розмір. Іншими словами, побудований таким чином, список масивів починає своє життя порожнім.

Один із способів додати десять елементів до списку масивів - за допомогою циклу:

for (int i = 0; i < 10; i++) {
  arr.add(0);
}

Зробивши це, тепер ви можете змінювати елементи в індексах 0..9.


51
+1: Коротша петля. while(arr.size() < 10) arr.add(0);Це може бути корисно сказати, розмір повинен бути принаймні 10. Наприклад, щоб ви могли використовуватиarr.set(9, n);
Пітер Лорі

10
+1: Чудова відповідь, я б дав +10, якби міг. З api не відразу зрозуміло, чому ви не можете встановити BOTH початковий розмір та початкову потужність в одному виклику конструктора. Вам належить прочитати api і сказати "О, я думаю, у ArrayList немає методу чи конструктора для цього"
demongolem

@PeterLawrey Ваш код може бути коротшим, але містить два виклики методу за цикл ітерації, а не один.
нейронмер

@neuralmer Я б очікував, що розмір () і add () буде вкладений, тому фактичний виклик методу не відбувається під час виконання.
Пітер Лорі

109

Якщо вам потрібен список із заданим розміром, ви також можете скористатися:

List<Integer> arr = Arrays.asList(new Integer[10]);

11
Тут невеликий недолік, в результаті чого Listповно нулів. З Guava ми можемо зробити це, Ints.asList(new int[10])яке буде ініціалізувати наш список з 0s. Чистий візерунок, хоча, дякую за приклад.
dimo414

1
Питання розповідають про ArrayList <E>. Ви використовуєте Список <E>. Ніхто цього не спостерігав ??? Більше того, вони підтримали цю нерелевантну відповідь! Я не спростовую вашу відповідь, тому що я ніколи цього не роблю. Просто ... Годо!
Апостолос

3
@Apostolos ArrayListє реалізацією Listінтерфейсу і Arrays.asListповертає ArrayList. Я пропоную вам шукати поліморфізм.
Ліам Поттер

Це повертає список з фіксованим розміром. Намагаючись додати більше елементів кидківUnsupportedOperationException
Корай Тугай

47

якщо ви хочете використовувати Collections.fill (список, obj); для того, щоб заповнити список повторним об'єктом або ви можете використовувати

ArrayList<Integer> arr=new ArrayList<Integer>(Collections.nCopies(10, 0));

рядок копіює 10 разів 0 у ваш ArrayList


20

Ємність з ArrayListне те ж саме , як її розмір . Розмір дорівнює кількості елементів, що містяться в ArrayList(та будь-якій іншій Listреалізації).

Потужності просто довжина основного масиву , який використовується для зберігання internaly елементів ArrayList, і завжди більше або дорівнює розміру списку.

Під час виклику set(index, element)у списку indexстосується фактичної кількості елементів списку (= розмір) (який у вашому коді дорівнює нулю, тому AIOOBEвикидається), а не до довжини масиву (= місткість) (що є детальною деталлю про реалізацію до ArrayList).

setМетод є загальним для всіх Listреалізацій, наприклад LinkedList, яка на самому ділі не реалізована масивом, але в якості пов'язаної ланцюжка записів.

Редагувати : Ви фактично використовуєте add(index, element)метод set(index, element), але ні , але тут принцип однаковий.


10

Якщо ви хочете додати елементи з індексом, замість цього ви можете використовувати масив.

    String [] test = new String[length];
    test[0] = "add";

5
OP хотів спочатку використовувати Список ... а не масив.
Стефан

9

10 - початкова ємність АЛ, а не розмір (який дорівнює 0). Ви повинні згадати початкову ємність до деякого високого значення, коли у вас буде багато елементів, оскільки це дозволяє уникнути накладних витрат на розширення ємності, коли ви продовжуєте додавати елементи.


6

Думаю, точним відповіді на ваше запитання було б:

Встановлення розміру intial на ArrayList зменшує nr. разів має відбуватися перерозподіл внутрішньої пам'яті. Список підтримується масивом. Якщо вказати початкову ємність 0, вже при першій вставці елемента внутрішній масив повинен був би змінити розмір. Якщо у вас є приблизне уявлення про те, скільки елементів міститиме ваш список, встановлення початкової ємності призведе до зменшення nr. перерозподілу пам'яті, що відбувається під час використання списку.



3

Запізнившись на це, але після Java 8 я особисто вважаю цей наступний підхід з StreamAPI більш стислим і може стати альтернативою прийнятій відповіді .

Наприклад,

Arrays.stream(new int[size]).boxed().collect(Collectors.toList())

де sizeпотрібний Listрозмір і без згаданого тут недоліку , всі елементи в Listініціалізовані як 0.

(Я швидко здійснив пошук і не побачив streamжодної публікації відповідей - не соромтеся повідомити мене, чи ця відповідь є зайвою, і я можу її видалити)


1

Зараз у вашому списку немає елементів, тому ви не можете додавати до індексу 5 списку, коли його не існує. Ви плутаєте ємність списку з його поточним розміром.

Просто зателефонуйте:

arr.add(10)

щоб додати Integer до свого ArrayList


1

Незважаючи на те, що ваш арселіст має 10 міст, реальний список тут не містить елементів. Метод add використовується для вставки елемента до реального списку. Оскільки у нього немає елементів, ви не можете вставити елемент до індексу 5.


1

Якщо ви хочете додати до себе 10 елементів, ArrayListви можете спробувати це:

for (int i = 0; i < 10; i++)
    arr.add(i);

Якщо ви вже оголосили змінну розміру масиву, ви б використовували змінну sizeзамість числа "10"


1

Я зіткнувся з подібною проблемою, і просто знаючи, що arrayList - це реалізація змінної масиву інтерфейсу List, я також очікую, що ви можете додати елемент до будь-якої точки, але принаймні мати можливість визначити початковий розмір. У будь-якому випадку, ви можете створити масив спочатку та перетворити його у такий список:

  int index = 5;
  int size = 10;

  Integer[] array = new Integer[size];
  array[index] = value;
  ...
  List<Integer> list = Arrays.asList(array);

або

  List<Integer> list = Arrays.asList(new Integer[size]);
  list.set(index, value);

0

ArrayList myList = новий ArrayList (10);

//  myList.add(3, "DDD");
//  myList.add(9, "III");
    myList.add(0, "AAA");
    myList.add(1, "BBB");

    for(String item:myList){
        System.out.println("inside list : "+item);
    }

/ * Оголосити початкову покараність arraylist - це не що інше, як економія зрушення часу на внутрішню; коли ми додаємо елемент внутрішньо, він перевіряє capasity, щоб збільшити capasity, ви можете додати елемент у 0 індексу спочатку, а потім 1 і так далі. * /


0

Мої два центи на Stream. Я думаю, що краще використовувати

IntStream.generate(i -> MyClass.contruct())
         .limit(INT_SIZE)
         .collect(Collectors.toList());

з гнучкістю ставити будь-які початкові значення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.