Bună! În lecțiile anterioare, am făcut o scufundare profundă în matrice și am analizat exemple comune de lucru cu matrice. În această lecție, vom analiza mai detaliat Java ArrayList. În general, matricele sunt foarte utile. Și, după cum ați observat deja, puteți face multe cu ele :) Dar matricele au o serie de deficiențe.
  • Dimensiune limitata. Trebuie să știți câte elemente trebuie să conțină matricea dvs. în momentul în care o creați. Dacă subestimezi, atunci nu vei avea suficient spațiu. Supraestimați, iar matricea va rămâne pe jumătate goală, ceea ce este de asemenea rău. La urma urmei, încă alocați mai multă memorie decât este necesar.

  • O matrice nu are metode de adăugare a elementelor. Trebuie să indicați întotdeauna în mod explicit indexul poziției în care doriți să adăugați un element. Dacă specificați accidental indexul pentru o poziție ocupată de o valoare de care aveți nevoie, acesta va fi suprascris.

  • Nu există metode de a șterge un articol. O valoare poate fi doar „redusă la zero”.

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 + '\'' +
               '}';
   }
}
Ieșire: [Cat{name='Thomas'}, null, Cat{name='Lionel Messi'}] Din fericire, creatorii Java sunt foarte conștienți de avantajele și dezavantajele matricelor și, prin urmare, au creat o structură de date foarte interesantă numită Java ArrayList . Vorbind cât se poate de simplu, o listă Java ArrayList este o matrice „completă” cu o mulțime de caracteristici noi.

Cum se creează o ArrayList

Este foarte ușor de creat:

ArrayList<Cat> cats = new ArrayList<Cat>();
Acum am creat o listă pentru stocarea obiectelor Cat . Rețineți că nu specificăm dimensiunea ArrayList , deoarece se poate extinde automat. Cum este posibil acest lucru? Este destul de simplu, de fapt. S-ar putea să vă surprindă, dar ArrayList în Java este construit pe deasupra unui tablou foarte obișnuit :) Da, conține o matrice și acolo sunt stocate elementele noastre. Dar ArrayList în Java are un mod special de a lucra cu acea matrice:
  • Când matricea internă este umplută, ArrayList creează o nouă matrice intern. Dimensiunea noii matrice este dimensiunea vechii matrice înmulțit cu 1,5 plus 1.

  • Toate datele sunt copiate din vechea matrice în cea nouă

  • Vechea matrice este curățată de colectorul de gunoi.
Acest mecanism permite Java ArrayList (spre deosebire de o matrice obișnuită) să implementeze o metodă pentru adăugarea de noi elemente. Este add()metoda

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<Cat>();
   cats.add(new Cat("Behemoth"));
}
Articole noi sunt adăugate la sfârșitul listei. Acum nu există niciun risc să depășească matricea, așa că această metodă este complet sigură. Apropo, ArrayList poate găsi nu numai un obiect după indexul său, ci și invers: poate folosi o referință pentru a găsi indexul unui obiect în ArrayList ! Pentru asta este metoda indexOf() : trecem o referință la obiectul pe care îl dorim, iar indexOf() returnează indexul său:

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);
}
Ieșire: 0 Așa este. Obiectul nostru thomas este într-adevăr stocat în elementul 0. Matricele nu au doar dezavantaje. Au si avantaje incontestabile. Una dintre ele este capacitatea de a căuta elemente după index. Deoarece indicăm către un index, adică către o anumită adresă de memorie, căutarea într-o matrice în acest mod este foarte rapidă. ArrayListștie și cum să o facă! Metoda get() implementează:

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);
}
Ieșire: Cat{name='Behemoth'} În plus, puteți afla cu ușurință dacă ArrayList conține un anumit obiect. Acest lucru se face folosind metoda 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));
}
Metoda verifică dacă tabloul intern al ArrayList conține elementul și returnează un boolean (adevărat sau fals). Ieșire: fals Și încă un lucru important despre inserție. ArrayList vă permite să utilizați un index pentru a insera elemente nu numai la sfârșitul matricei, ci oriunde. Are două metode pentru aceasta:
  • ArrayList add (index int, element Cat)
  • Set ArrayList (index int, element Cat)
Ca argumente, ambele metode iau indexul poziției în care doriți să inserați și o referință la obiectul în sine. Diferența este că inserarea folosind set() suprascrie vechea valoare. Inserarea folosind add() mută mai întâi cu unul toate elementele de la [index] la sfârșitul matricei, apoi adaugă obiectul specificat în poziția goală rezultată.

Iată un exemplu:


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());
}
Ieșire: [[Cat{name='Thomas'}, Cat{name='Behemoth'}] [Cat{name='Lionel Messi'}, Cat{name='Behemoth'}] Aveam o listă de 2 pisici . Apoi am inserat altul ca element 0 folosind metoda set() . Ca urmare, vechiul element a fost înlocuit cu unul nou.

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());
}
Și aici vedem că add() funcționează diferit. Mută ​​toate elementele spre dreapta și apoi scrie noua valoare ca element 0. Ieșire: [Cat{name='Thomas'}, Cat{name='Behemoth'}] [Cat{name='Lionel Messi'}, Cat{name='Thomas'}, Cat{name='Behemoth'}] Pentru a șterge complet lista, folosim metoda 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());
}
Ieșire: [] Totul a fost eliminat din listă. Apropo, vă rugăm să rețineți: spre deosebire de matrice, ArrayList suprascrie metoda toString() și afișează deja lista în mod corespunzător ca șiruri. Cu matrice obișnuite, a trebuit să folosim clasa Arrays pentru asta. Și din moment ce am menționat Arrays : Java vă permite să „comutați” cu ușurință între o matrice și o ArrayList , adică să convertiți unul în altul. Clasa Arrays are o metodă Arrays.asList() pentru aceasta. Îl folosim pentru a obține conținutul ca o matrice și pentru a le transmite constructorului nostru 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);
}
Ieșire: [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}] Puteți merge și în direcția opusă: obțineți o matrice dintr-un obiect ArrayList . Facem acest lucru folosind metoda 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));
}
Notă: am trecut o matrice goală metodei toArray() . Aceasta nu este o eroare. În cadrul clasei ArrayList , această metodă este implementată în așa fel încât trecerea unei matrice goale crește performanța acesteia. Țineți cont de acest lucru pentru viitor (desigur, puteți trece o matrice de o anumită dimensiune; și asta va funcționa). Oh, cam de mărime. Mărimea curentă a listei poate fi găsită folosind metoda 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());
}
Este important să înțelegeți că, spre deosebire de proprietatea de lungime a unui tablou, metoda ArrayList.size() returnează numărul real de elemente, nu capacitatea originală. La urma urmei, nu am specificat o dimensiune când am creat ArrayList . Cu toate acestea, îl puteți specifica — ArrayList are un constructor adecvat. Dar în ceea ce privește adăugarea de noi elemente, acest lucru nu îi schimbă comportamentul:

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());
}
Ieșire din consolă: 4 Am creat o listă de 2 elemente, dar s-a extins în liniște când am avut nevoie. O altă considerație este că, dacă creăm inițial o listă foarte mică, va trebui să se extindă mai des, ceea ce va folosi unele resurse. Cu greu am atins procesul de eliminare a elementelor dintr-o ArrayList în această lecție. Desigur, acest lucru nu se datorează faptului că ne-a scăpat mintea. Am pus acest subiect într-o lecție separată pe care o veți întâlni mai târziu :) Pentru a consolida ceea ce ați învățat, vă sugerăm să urmăriți o lecție video de la Cursul nostru Java