miercuri, 25 februarie 2026

Clasa ArrayList. Crearea listelor dinamice de obiecte

După ce am învățat să lucrăm cu vectori de obiecte, este momentul să facem un pas mai departe. Până acum am creat structuri de tipul:  

Elev[] elevi = new Elev[30];

Unde
Elev[] înseamnă un vector care poate stoca obiecte de tip Elev;
30 reprezintă numărul maxim de elemente;
fiecare poziție din vector reține un obiect.

Această metodă este corectă și foarte importantă pentru a înțelege cum funcționează memoria și organizarea datelor. 
Dar în aplicarea în practică, uneori această metodă este ineficientă. 
De ce?  Pentru că așa tip de vector are o dimensiune statică, în sens că dimensiunea acestuia este fixă, iar în cazul exemplului de mai sus nu vom putea adăuga al 31-lea elev, ba mai mult dacă inserăm în listă doar 10 elevi, restul pozițiilor rămân neutilizate. Ștergerea unui element necesită mutarea manuală a celorlalte.

În aplicațiile reale, de cele mai multe ori nu știm din start câte obiecte vom avea. Nu avem cum să cunoaștem câte persoane se vor înscrie la un concurs, câte persoane își vor crea conturi pe platforma educațională a instituției sau câți abiturienți vor depune dosarul pentru a participa la concursul de admitere. Respectiv, este nevoie de o structură dinamică dimensiunea căreia să fie ajustabilă.

Una din soluțiile care le oferă limbajul Java este utilizarea clasei ArrayList din pachetul java.util.  
Un ArrayList este un vector dinamic. Aceasta înseamnă că dimensiunea se modifică automat, avem posibilitatea de a adăuga elemente fără limită fixă, iar ștergerea elementelor este simplificată. 

După cum cunoaștem ca să creăm listă dinamică este necesar de instanțiat clasa ArrayList , deci trebuie să îi cunoaștem constructorii: 
ArrayList() Construiește o listă fără nici un element având capacitatea inițială de 10 elemente. Dacă se încearcă adăugarea a mai mult de 10 elemente, dimensiunea listei se va modifica automat.
ArrayList(Collection c) Construiește o listă ce conține elementele conținute de colecția primită ca argument. Capacitatea inițială este cu 10 procente mai mare decât numărul de elemente din colecția primită ca argument
ArrayList(int intialCapacity) Construiește o listă vidă cu o capacitate specificată de parametrul intialCapacity

Deci pentru a crea un ArrayList respectăm sintaxa: 
ArrayList<Elev> listaElevi = new ArrayList<>();

După cum observați dimensiunea listei nu o mai specificăm, așa cum aceasta crește automat. 

Pentru a putea opera cu elementele din listă vom trebuie să cunoaștem metodele clasei ArrayList și parametrii acestora:
 
1. add(E e)- adaugă la sfârșitul listei obiectul e
ArrayList<String> lista = new ArrayList<>();
lista.add("Ana"); // adaugă "Ana" în listă
lista.add("Ion"); // adaugă "Ion" în listă

2. add(int index, E e) - adaugă obiectul e în listă începând cu poziția index, mutând elementele de după el.
lista.add(1, "Maria"); // inserează "Maria" pe poziția 1

3. get(int index) - returnează elementul de la poziția indicată prin parametrul index
String nume = lista.get(0); // returnează "Ana"

4. set (int index, E e)- Înlocuiește elementul de pe poziția index cu noul element, sau obiect e
lista.set(0, "Andreea"); // înlocuiește "Ana" cu "Andreea" 

5. remove(int index)- șterge elementul de la poziția indicată și mută elementele următoare.
lista.remove(1); // șterge elementul de pe poziția 1 ("Maria")

6. remove(Object o) - șterge prima apariție a obiectului o din listă.
lista.remove("Andreea"); // șterge "Andreea" din listă

7.
size()- returnează numărul de elemente din listă.
int lungime = lista.size(); // returnează 0 dacă lista este goală

8. isEmpty()- returnează true dacă lista este goală.
if (lista.isEmpty()) {
System.out.println("Lista este goală");}

9. contains(Object o) - verifică dacă lista conține elementul dat.
boolean exista = lista.contains("Ion"); // returnează true dacă "Ion" este în listă

10. clear()- șterge toate elementele din listă.
lista.clear(); // lista devine goală

Crearea unei liste de tip ArrayList care să conțină direct tipuri primitive precum int sau double nu este posibilă, așa cum metodele clasei ArrayList operează cu tip de date referință. 

Totuși, încă de la începutul cursului am învățat că fiecărui tip primitiv din Java îi corespunde o clasă de tip Wrapper.
De exemplu:
tipului int îi corespunde clasa Integer
tipului double îi corespunde clasa Double
tipului char îi corespunde clasa Character
tipului boolean îi corespunde clasa Boolean

Astfel, dacă dorim o listă de numere întregi, vom scrie:
ArrayList<Integer> numere = new ArrayList<>();
numere.add(10);
numere.add(25);

Observați că folosim Integer, nu int.
Java face automat conversia dintre tipul primitiv și obiectul corespunzător. Acest mecanism se numește autoboxing (transformarea automată a unui tip primitiv într-un obiect Wrapper) și unboxing (transformarea inversă).

În exemplele de mai sus, elementele stocate în ArrayList sunt de tip String, pentru a simplifica înțelegerea. În practică însă, lista va conține, de cele mai multe ori, obiecte ale claselor create de programator, cum ar fi Client, Produs, Comandă sau alte tipuri definite în aplicație.

Să vedem în următorul exemplu cum este posibil acest lucru. 
Fie ca avem clasa Elev cu următorul cod sursă:
 
class Elev{
private String nume;
private int grupa;
 
public Elev(String nume, int grupa) {
this.nume = nume;
this.grupa = grupa;
}
public String getNume() {
return nume; }
 
public void setNume(String nume) {
this.nume = nume;
}
 
public int getGrupa() { return grupa; }
 
public void setGrupa(int grupa) {
this.grupa = grupa;
}} 

Următorul exemplu va crea o listă de elevi și va parcurge elementele acesteia folosind instrucțiunea for clasică cu index:

import java.util.*;
class TestCollection1{
    public static void main(String args[]){
        ArrayList<Elev> lista=new ArrayList<Elev>();
        lista.add(new Elev("Ana", 1001));
        lista.add(new Elev("Maria", 1002));
        lista.add(new Elev("Ion", 1001));
        lista.add(new Elev("Mihai", 1002));
        for (int i = 0; i < lista.size(); i++) {
            Elev element = lista.get(i);
            System.out.println(element.getNume()+
                    " "+element.getGrupa());}
    }}

O altă modalitate de a parcurge lista este instrucțiunea for îmbunătățit, dar ... noi deja cunoaștem în ce context o folosim 👌

import java.util.*;
class TestCollection1{
    public static void main(String args[]){
         ArrayList<Elev> lista=new ArrayList<Elev>();
         lista.add(new Elev("Ana", 1001));
         lista.add(new Elev("Maria", 1002));
         lista.add(new Elev("Ion", 1001));
         lista.add(new Elev("Mihai", 1002));
         for (Elev element : lista) {
             System.out.println(element.getNume()+
             " "+element.getGrupa());}

    }}


Voi prezenta mai jos o metodă de parcurgere a listei destul de des folosită în proiecte reale: 
import java.util.*;
class TestCollection1{
    public static void main(String args[]){
        ArrayList<Elev> lista=new ArrayList<Elev>();
        lista.add(new Elev("Ana", 1001));
        lista.add(new Elev("Maria", 1002));
        lista.add(new Elev("Ion", 1001));
        lista.add(new Elev("Mihai", 1002));
        lista.forEach(element -> {
            System.out.println(element.getNume()+
                    " "+element.getGrupa());
        });
    }}

Metoda
forEach(element -> { ... }) din ultimul exemplu folosește o expresie lambda pentru parcurgerea listei.  Expresiile lambda sunt o funcționalitate în limbaj introdusă în Java8. Tradus din limbaj Java în limbaj omenesc ar însemna: ,,pentru fiecare element din listă, execută instrucțiunile din bloc”.

Sunt și alte metode de parcurgere și modificare a listelor de obiecte cum ar fi interfața Iterator, Interfața Enumeration, dar vom discuta despre ele într-o altă postare.

Succes!
❤️

Niciun comentariu:

Trimiteți un comentariu

Vă mulțumesc pentru feedback!