CodeGym /Java блог /Случаен /ArrayList в снимки
John Squirrels
Ниво
San Francisco

ArrayList в снимки

Публикувано в групата
здрасти Днешният урок ArrayListще бъде едновременно по-лесен и по-труден от предишните уроци.
ArrayList в снимки - 1
Ще бъде по-трудно, защото днес ще погледнем под капака ArrayListи ще проучим Howво се случва по време на различни операции. От друга страна, този урок няма да има почти ниHowъв code. Това са предимно снимки и обяснения. Е, да тръгваме :) Както вече знаете, ArrayListима обикновен масив вътре, който действа като хранorще на данни. В повечето случаи не посочваме точния размер на списъка. Но вътрешният масив трябва да има няHowъв размер! И така става. Размерът му по подразбиране е 10 .

public static void main(String[] args) {
   ArrayList<Car> cars = new ArrayList<>();
}
ArrayList в снимки - 2 Първо, нека видим How изглежда добавянето на нови елементи. Първата работа е да се провери дали вътрешният масив има достатъчно място във вътрешния масив и дали ще се побере още един елемент. Ако има място, новият елемент се добавя в края на списъка. Когато казваме "до края", нямаме предвид последната позиция в масива (това би било странно). Имаме предвид позицията след последния текущ елемент. Индексът му ще бъде cars.size(). Нашият списък в момента е празен ( cars.size() == 0). Съответно новият елемент ще бъде добавен на позиция 0.

ArrayList<Car> cars = new ArrayList<>();
Car ferrari = new Car("Ferrari 360 Spider");
cars.add(ferrari);
ArrayList в снимки - 3 Това е достатъчно ясно. Какво се случва, ако вмъкнем в средата, т.е. между други елементи?

public static void main(String[] args) {
   ArrayList<Car> cars = new ArrayList<>();
   Car ferrari = new Car("Ferrari 360 Spider");
   Car bugatti = new Car("Bugatti Veyron");
   Car lambo = new Car("Lamborghini Diablo");
   Car ford = new Car("Ford Modneo");
  
   cars.add(ferrari);
   cars.add(bugatti);
   cars.add(lambo);
  
   cars.add(1, ford);// add ford to cell 1, which is already occupied
}
Отново първо се проверява дали има достатъчно място в масива. Ако има достатъчно място, тогава елементите се изместват надясно , започвайки от позицията, където вмъкваме новия елемент. Вмъкваме в позиция 1. С други думи, елементът от позиция 3 се копира в позиция 4, елемент 2 в позиция 3 и елемент 1 в позиция 2. След това ArrayList в снимки - 4 нашият нов елемент се вмъква на негово място. Предишният елемент (bugatti) вече е копиран от там на нова позиция. ArrayList в снимки - 5 Сега нека да разгледаме How се случва този процес, ако няма места за вмъкване на нови елементи в масива. ArrayList в снимки - 6 Естествено, първо се проверява дали има достатъчно място. Ако няма достатъчно място, тогава се създава нов масив вътре вArrayListчийто размер е размерът на стария масив, умножен по 1,5 плюс 1. В нашия случай размерът на новия масив ще бъде 16. Всички текущи елементи ще бъдат копирани веднага там. ArrayList в снимки - 7 Старият масив ще бъде изтрит от събирача на отпадъци и ще остане само новият, разширен масив. Сега има място за нов елемент. Вмъкваме го на позиция 3, която е заета. Сега започва познатата proceduresа. Всички елементи, започващи с индекс 3, се изместват една позиция надясно и новият елемент се добавя тихо. ArrayList в снимки - 8 И вмъкването е готово! И сме готови с вмъкването. Сега нека поговорим за премахването на елементи . Ще си спомните, че се натъкнахме на проблем при работа с масиви: премахването на елементи прави „дупки“ в масива.с всяко премахване и трябваше да пишем собствен code всеки път, за да извършим тази смяна. ArrayList следва същия принцип, но вече прилага този механизъм. ArrayList в снимки - 9 Ето How изглежда: ArrayList в снимки - 10 И в крайна сметка получаваме това, което искаме: ArrayList в снимки - 11 Елементът lamboе премахнат. Тук премахнахме елемент от средата. Ясно е, че премахването на елемент от края на списъка е по-бързо, тъй като елементът просто се премахва, без да е необходимо да се преместват всички останали. Нека поговорим отново за момент за размерите на вътрешния масив и How е подреден в паметта. Разширяването на масив отнема известни ресурси. Съответно, не създавайтеArrayListс размера по подразбиране, ако сте сигурни, че ще има поне 100 елемента. Вътрешният масив ще трябва да бъде разширен 6 пъти до момента, в който вмъкнете 100-ия елемент, и всички елементи ще трябва да се изместват всеки път.
  • от 10 елемента до 16
  • от 16 елемента на 25
  • от 25 до 38
  • от 38 до 58
  • от 58 до 88
  • от 88 до 133 (т.е. размерът на стария масив по 1,5 плюс 1)
Както можете да си представите, това е доста ресурсоемко. Така че, ако вече знаете (дори приблизително) необходимия брой елементи, по-добре е да създадете списък с масив с определен размер:

ArrayList<Car> cars = new ArrayList<>(100);
Сега паметта за масив от 100 елемента ще бъде разпределена наведнъж, което ще направи масива по-ефективен (няма да има нужда да се разширява). Тази стратегия има и обратна страна. Когато премахвате обекти от ArrayList, размерът на вътрешния масив не намалява автоматично. Да предположим, че имаме ArrayListс напълно пълен вътрешен масив от 88 елемента: ArrayList в снимки - 12 Докато програмата работи, ние премахваме 77 елемента, така че остават само 11: ArrayList в снимки - 13 Вече познахте ли Howъв е проблемът? Разбрахте, неефективно използване на паметта! Тук използваме само 11 позиции, но сме заделor памет за 88 елемента. Това е 8 пъти повече, отколкото ни трябва! В този случай можем да оптимизираме използването на нашата памет с един от ArrayListспециалните методи на класа:trimToSize(). Този метод "подрязва" дължината на вътрешния масив до броя на елементите, съхранявани в момента в него. ArrayList в снимки - 14 Сега сме разпределor само толкова памет, колкото ни е необходима! :)
Коментари
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION