John Squirrels
Ниво
San Francisco

Java ArrayList

Публикувано в групата
здрасти В предишните уроци се потопихме дълбоко в масивите и прегледахме общи примери за работа с масиви. В този урок ще направим по-подробен преглед на Java ArrayList. Като цяло масивите са супер удобни. И Howто вече забелязахте, можете да направите много с тях :) Но масивите имат редица недостатъци.
  • Ограничен размер. Трябва да знаете колко елемента трябва да съдържа вашият масив в момента, в който го създавате. Ако подцените, няма да имате достатъчно място. Надценете и масивът ще остане полупразен, което също е лошо. В края на краищата вие все още отделяте повече памет, отколкото е необходимо.

  • Масивът няма методи за добавяне на елементи. Винаги трябва изрично да посочите индекса на позицията, където искате да добавите елемент. Ако случайно посочите индекса за позиция, заета от необходимата ви стойност, тя ще бъде презаписана.

  • Няма методи за изтриване на елемент. Една стойност може да бъде само "нулирана".

public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public static void main(String[] args) {

       Cat[] cats = new Cat[3];
       cats[0] = new Cat("Thomas");
       cats[1] = new Cat("Behemoth");
       cats[2] = new Cat("Lionel Messi");

       cats[1] = null;

      
      
       System.out.println(Arrays.toString(cats));
   }

   @Override
   public String toString() {
       return "Cat{" +
               "name='" + name + '\'' +
               '}';
   }
}
Резултат: [Cat{name='Thomas'}, null, Cat{name='Lionel Messi'}] За щастие, създателите на Java са добре запознати с предимствата и недостатъците на масивите и затова създадоха много интересна структура от данни, наречена Java ArrayList . Говорейки възможно най-просто, Java ArrayList е "подсилен" масив с много нови функции.

Как да създадете ArrayList

Създаването е много лесно:

ArrayList<Cat> cats = new ArrayList<Cat>();
Сега създадохме списък за съхраняване на Cat обекти. Обърнете внимание, че не указваме размера на ArrayList , защото той може да се разширява автоматично. Как е възможно? Всъщност е доста просто. Може да ви изненада, но ArrayList в Java е изграден върху много обикновен масив :) Да, той съдържа масив и там се съхраняват нашите елементи. Но ArrayList в Java има специален начин за работа с този масив:
  • Когато вътрешният масив се запълни, ArrayList създава вътрешно нов масив. Размерът на новия масив е размерът на стария масив, умножен по 1,5 плюс 1.

  • Всички данни се копират от стария масив в новия

  • Старият масив се почиства от боклукчия.
Този механизъм позволява на Java ArrayList (за разлика от обикновения масив) да реализира метод за добавяне на нови елементи. Това е add()методът

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<Cat>();
   cats.add(new Cat("Behemoth"));
}
Нови елементи се добавят в края на списъка. Сега няма риск от препълване на масива, така че този метод е напълно безопасен. Между другото, ArrayList може не само да намери обект по неговия индекс, но и обратното: може да използва препратка, за да намери индекса на обект в ArrayList ! Ето за Howво служи методът indexOf() : Предаваме препратка към обекта, който искаме, и indexOf() връща неговия индекс:

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   int thomasIndex = cats.indexOf(thomas);
   System.out.println(thomasIndex);
}
Изход: 0 Точно така. Нашият обект thomas наистина се съхранява в елемент 0. Масивите нямат само недостатъци. Те също имат безспорни предимства. Една от тях е възможността за търсене на елементи по индекс. Тъй като сочим към индекс, т.е. към определен address в паметта, търсенето в масив по този начин е много бързо. ArrayListсъщо знае How да го направи! Методът get() прилага това:

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   Cat secondCat = cats.get(1);

   System.out.println(secondCat);
}
Изход: Cat{name='Behemoth'} Освен това можете лесно да разберете дали ArrayList съдържа конкретен обект. Това се прави с помощта на метода ArrayList contains():

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   cats.remove(fluffy);
   System.out.println(cats.contains(fluffy));
}
Методът проверява дали вътрешният масив на ArrayList съдържа елемента и връща булево meaning (true or false). Изход: false И още нещо важно за вмъкването. ArrayList ви позволява да използвате индекс за вмъкване на елементи не само в края на масива, но навсякъде. Има два метода за това:
  • ArrayList add(int индекс, Cat елемент)
  • ArrayList набор (int индекс, Cat елемент)
Като аргументи и двата метода приемат индекса на позицията, където искате да вмъкнете, и препратка към самия обект. Разликата е, че вмъкването с помощта на set() презаписва старата стойност. Вмъкването с помощта на add() първо измества с един всички елементи от [index] до края на масива и след това добавя посочения обект в получената празна позиция.

Ето един пример:


public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);

   System.out.println(cats.toString());

   cats.set(0, lionel);// Now we have a list of 2 cats. Adding a 3rd using set

   System.out.println(cats.toString());
}
Резултат: [[Cat{name='Thomas'}, Cat{name='Behemoth'}] [Cat{name='Lionel Messi'}, Cat{name='Behemoth'}] Имахме списък от 2 котки . След това вмъкнахме още един като елемент 0, използвайки метода set() . В резултат на това старият елемент е заменен с нов.

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);

   System.out.println(cats.toString());

   cats.add(0, lionel);// Now we have a list of 2 cats. Adding a 3rd using add

   System.out.println(cats.toString());
}
И тук виждаме, че add() работи по различен начин. Той премества всички елементи надясно и след това записва новата стойност като елемент 0. Изход: [Cat{name='Thomas'}, Cat{name='Behemoth'}] [Cat{name='Lionel Messi'}, Cat{name='Thomas'}, Cat{name='Behemoth'}] За да изчистим напълно списъка, използваме метода clear() :

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   cats.clear();

   System.out.println(cats.toString());
}
Изход: [] Всичко беше премахнато от списъка. Между другото, имайте предвид: за разлика от масивите, ArrayList заменя метода toString() и вече показва списъка по подходящ начин като низове. С обикновените масиви трябваше да използваме класа Arrays за това. И тъй като споменах масиви : Java ви позволява лесно да "превключвате" между масив и ArrayList , т.е. да конвертирате един в друг. Класът Arrays има метод Arrays.asList() за това. Използваме го, за да получим съдържанието като масив и да го предадем на нашия конструктор ArrayList :

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();


   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   Cat[] catsArray = {thomas, behemoth, lionel, fluffy};

   ArrayList<Cat> catsList = new ArrayList<>(Arrays.asList(catsArray));
   System.out.println(catsList);
}
Изход: [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}] Можете също да отидете в обратната посока: get масив от обект ArrayList . Правим това с помощта на метода toArray() :

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();

   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   Cat[] catsArray = cats.toArray(new Cat[0]);

   System.out.println(Arrays.toString(catsArray));
}
Забележка: предадохме празен масив на метода toArray() . Това не е грешка. Вътре в класа ArrayList този метод е имплементиран по такъв начин, че предаването на празен масив увеличава неговата производителност. Просто имайте предвид това за в бъдеще (разбира се, можете да подадете масив с определен размер; това също ще работи). О, за размера. Текущият размер на списъка може да бъде намерен с помощта на метода size() :

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();


   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   System.out.println(cats.size());
}
Важно е да разберете, че за разлика от свойството дължина на масива , методът ArrayList.size() връща действителния брой елементи, а не първоначалния капацитет. В края на краищата, ние не посочихме размер, когато създавахме ArrayList . Можете обаче да го посочите - ArrayList има подходящ конструктор. Но по отношение на добавянето на нови елементи, това не променя поведението му:

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>(2);// create an ArrayList with an initial capacity of 2


   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   System.out.println(cats.size());
}
Изход за конзолата: 4 Създадохме списък от 2 елемента, но той тихо се разшири, когато ни трябваше. Друго съображение е, че ако първоначално създадем много малък списък, той ще трябва да се разширява по-често, което ще използва някои ресурси. Почти не сме засегнали процеса на премахване на елементи от ArrayList в този урок. Разбира се, това не е защото ни се е изплъзнало от ума. Поставихме тази тема в отделен урок, с който ще се запознаете по-късно :) За да затвърдите наученото, ви предлагаме да гледате видео урок от нашия курс по Java
Коментари
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION