Differences

This shows you the differences between two versions of the page.

Link to this comparison view

poo:breviare:breviar-07 [2020/11/17 10:58]
mihai.nan
poo:breviare:breviar-07 [2025/11/19 09:25] (current)
george.tudor1906
Line 1: Line 1:
 ====== Breviar 7 ====== ====== Breviar 7 ======
  
 +=== Colecții, iteratori, genericitate ===
  
 +=== 1. Colecții ===
  
-<HTML+== 1.1 Interfața Collection și ierarhia colecțiilor == 
-  <iframe src="https://docs.google.com/file/d/1sm4EqZihlBQWomEfEXRwojJ0WBjwrDL2/preview" ​width="640" ​height="720"></​iframe+ 
-</HTML>+{{:​poo:​breviare:​collection.png?​600|}} 
 + 
 +O **colecție** este un obiect care grupează mai multe elemente într-o singură unitate. Prin intermediul colecțiilor avem acces la diferite structuri de date: vectori dinamici, liste înlănțuite,​ stive, mulțimi, tabele de dispersie ș.a.m.d.. Colecțiile sunt folosite atât pentru **memorarea și manipularea datelor**, cât și pentru **transmiterea informațiilor între metode**. 
 + 
 +Clasele și interfețele pentru lucrul cu colecții se află în pachetul **java.util**. Ierarhia pornește, pentru colecții propriu-zise,​ de la interfața **Collection**,​ care definește operațiile de bază (adăugare, eliminare, căutare, iterare). Din //​Collection//​ derivă **trei ramuri principale**:​ 
 + 
 +  * **List** - colecții ordonate și indexate, care permit duplicate; implementările uzuale sunt ArrayList (acces aleator rapid) și LinkedList (inserări/​ștergeri eficiente cu iteratorul). Vector și Stack apar în bibliografie,​ dar sunt considerate tipuri legacy (fac parte din limbaj încă de la primele versiuni); pentru comportament de stivă/​coadă se preferă azi Deque (ex. ArrayDeque).  
 +  * **Set** - mulțimi fără duplicate (în sens matematic); aici întâlnim HashSet (rapid, neordonat), LinkedHashSet (păstrează ordinea inserării) și TreeSet (menține elementele ordonate). Ordonarea formală este surprinsă de interfața SortedSet, care extinde Set și cere o ordine „naturală” sau dată de un Comparator, TreeSet fiind implementarea clasică. 
 +  * **Queue** / **Deque** - structuri de tip coadă (eventual cu două capete). Implementările standard sunt ArrayDeque (coadă/​stivă eficientă) și PriorityQueue (ordonare după prioritate, nu după inserare). 
 + 
 +Separat de Collection se află ierarhia **Map**, care gestionează perechi cheie - valoare. Cheile sunt unice, iar fiecare cheie mapează exact o valoare. Implementările cele mai folosite sunt **HashMap** (rapid, fără ordine), **LinkedHashMap** (menține ordinea inserării sau a accesului - util, de exemplu, pentru cache LRU - Least Recently Used) și **TreeMap** (chei ordonate). Interfața **SortedMap** extinde Map cu operații specifice ordinii - în practică, TreeMap este implementarea reprezentativă. Hashtable este o variantă veche, sincronizată,​ păstrată pentru compatibilitate,​ dar în cod modern se preferă HashMap (sau ConcurrentHashMap pentru acces concurent). 
 + 
 +<note important
 +În Java modern, colecțiile sunt **parametrizate**:​ după numele colecției se declară, între //<​…>//,​ tipul elementelor. ​ De exemplu, //List<String>//​ înseamnă o listă care conține doar șiruri de caractere. 
 + 
 +Dacă tipul este declarat astfel, compilatorul verifică la compilare să nu introducem alt tip (de ex. un //Integer// într-o //​List<​String>//​). Orice încercare greșită este o **eroare de compilare**,​ deci problema se oprește înainte de rulare. 
 +</​note> ​  
 + 
 +<note warning>​ 
 +Colecțiile **eterogene** (elemente de orice fel) apar doar dacă: 
 +  * folosim intenționat un tip general (ex. //​List<​Object>//​),​ sau   
 +  * folosim un **raw type** (ex. //List// fără parametrul de tip).   
 + 
 +**Raw types** sunt permise, dar nerecomandate:​ dezactivează verificarea de tip la compilare și pot duce la //​ClassCastException//​ la rulare. Dacă aveți un caz real în care elementele pot fi de tipuri diferite, folosiți List<​Object>​ sau un tip comun (o interfață,​ o clasă părinte). </​note>​ 
 +<code java> 
 +import java.util.*;​ 
 + 
 +public class Main { 
 +    public static void main(String[] args) { 
 +        // 1) Corect și sigur - generics 
 +        List<​String>​ nume new ArrayList<>​();​ 
 +        nume.add("Ana"​);​ 
 +        // nume.add(10);​ // EROARE de compilare10 nu este String 
 +        String s1 = nume.get(0); ​// fără cast, sigur 
 + 
 +        // 2) Permis, dar nerecomandat - raw type (fără <​T>​) 
 +        List nespecificata = new ArrayList();​ // WARNING: unchecked/​unsafe 
 +        nespecificata.add("​Ana"​);​ 
 +        nespecificata.add(10);​ 
 +        String s2 = (String) nespecificata.get(1); ​// EXCEPȚIE la rulare: ClassCastException 
 + 
 +        ​// 3) Colecție heterogenă (intenționat) 
 +        List<​Object>​ mix = new ArrayList<>​();​ 
 +        mix.add("Ana"​);​ 
 +        mix.add(10);​ 
 +        Object o mix.get(1);​ 
 +        if (o instanceof Integer n) { 
 +            System.out.println(n + 5); // sigur 
 +        } 
 +    } 
 +
 +</​code>​ 
 + 
 +== 1.2 Liste (List) == 
 + 
 +Interfața **List**, pe lângă metodele moștenite din //​Collection//,​ definește colecții **ordonate** și **indexate**,​ care **permit duplicate** și ale căror elemente pot fi accesate după **poziție** (index). În practică, cele mai folosite implementări sunt **ArrayList** și **LinkedList**.  
 + 
 +ArrayList oferă **acces aleator foarte rapid** la elemente, cu cost mai mare pentru inserări/​ștergeri în interiorul listei. LinkedList stochează elementele într-o listă înlănțuită,​ ceea ce face **inserările și ștergerile** locale mai eficiente (folosind iteratorul),​ dar accesul la un element ​"din mijloc" ​este mai lent. LinkedList implementează și Deque, astfel că poate lucra comod cu elementele de la ambele capete (ex. addFirst, addLast). Pentru stivă/​coadă se preferă ArrayDeque, iar pentru liste obișnuite ArrayList/​LinkedList. 
 + 
 +<code java> 
 +import java.util.*;​ 
 + 
 +class Liste { 
 +    private final List<​String>​ list1 new ArrayList<>​(); ​       // ordonată, acces aleator rapid 
 +    private final LinkedList<​Integer>​ list2 = new LinkedList<>​();​ // listă + deque 
 + 
 +    public static void main(String[] args) { 
 +        Liste obj = new Liste(); 
 + 
 +        // Operații de bază pe ArrayList<​String>​ 
 +        obj.list1.add("Lab POO"); 
 +        obj.list1.add("​Colectii"​);​ 
 +        obj.list1.add("​Structuri de date"​);​ 
 +        if (obj.list1.contains("​Colectii"​)) { 
 +            System.out.println("​Lista contine cuvantul"​);​ 
 +        } 
 + 
 +        // Parcurgere și ștergere în siguranță (fără ConcurrentModificationException) 
 +        Iterator<​Stringit = obj.list1.iterator();​ 
 +        while (it.hasNext()) { 
 +            String s = it.next();​ 
 +            System.out.println(s);​ 
 +            it.remove();​ // șterge elementul tocmai citit 
 +        } 
 + 
 +        // LinkedList<Integer> ca listă + deque (ambele capete) 
 +        obj.list2.addAll(Arrays.asList(1,​ 10, 20)); 
 +        obj.list2.addFirst(50); ​// capătul din stânga 
 +        obj.list2.addLast(17); ​ // capătul din dreapta 
 + 
 +        // Modificare „pe loc” cu ListIterator (ex.: înmulțește numerele pare cu 10) 
 +        ListIterator<​Integerli = obj.list2.listIterator();​ 
 +        while (li.hasNext()) { 
 +            int x = li.next();​ 
 +            if (x % 2 == 0) li.set(x * 10); 
 +        } 
 + 
 +        // Afișare elemente (for-each) 
 +        for (Integer i : obj.list2) { 
 +            System.out.println(i);​ 
 +        } 
 + 
 +        // Sortare naturală (echivalent cu Collections.sort(list2)) 
 +        obj.list2.sort(Comparator.naturalOrder());​ 
 +        System.out.println(obj.list2);​ 
 +    } 
 +
 +</​code>​ 
 + 
 +<note tip> 
 +  * Declarați mereu tipul elementelor:​ //​List<​String>//,​ //​List<​Integer>//​. ​  
 +  * Pentru eliminări în timpul parcurgerii folosiți //​Iterator.remove()//​ sau //​removeIf(...)//​. ​  
 +  * Alegeți **ArrayList** când accentul este pe citire după index și **LinkedList** când aveți inserări/​ștergeri locale cu iteratorul sau operații la ambele capete. 
 +</​note> ​  
 + 
 +== 1.3 Mulțimi (Set și SortedSet) == 
 + 
 +**Set** modelează noțiunea de **mulțime** în sens matematic: nu pot exista două elemente //o1//, //o2// într-un Set pentru care //​o1.equals(o2)//​ este //true//. 
 +</​note> ​  
 + 
 +Set moștenește operațiile de bază din Collection, fără a introduce metode proprii. Implementări uzuale: 
 + 
 +  * **HashSet** - rapid, **neordonat**;​ 
 +  * **LinkedHashSet** - păstrează ordinea inserării;​ 
 +  * **TreeSet** - menține elementele **ordonate**. 
 + 
 +**SortedSet** reprezintă un Set în care elementele sunt păstrate în **ordine crescătoare**:​ 
 + 
 +  * fie după **ordinea naturală** (//​Comparable//​),​ 
 +  * fie după un //​Comparator//​ furnizat la crearea colecției. 
 + 
 +Implementarea standard de `SortedSet` este **TreeSet**. 
 + 
 +<note warning>​ 
 +Într-un **SortedSet**,​ pentru orice două obiecte o1, o2 ale colecției, //​o1.compareTo(o2)//​ sau //​comparator.compare(o1,​ o2)// trebuie să fie **valid** (fără excepții), iar pentru ordinea naturală, elementele //null// **nu sunt permise**. 
 +</​note> ​  
 + 
 +<code java> 
 +import java.util.*;​ 
 + 
 +class Example { 
 +    public static void main(String[] args) { 
 +        // 1) HashSet - fără ordine, elimină duplicatele pe baza equals()/​hashCode() 
 +        Set<​String>​ hs = new HashSet<>​();​ 
 +        Collections.addAll(hs,​ "​Ana",​ "​Ana",​ "​Ion"​);​ 
 +        System.out.println("​HashSet:​ " + hs); // ex.: [Ana, Ion] 
 + 
 +        // 2) LinkedHashSet - păstrează ordinea inserării 
 +        Set<​Integer>​ lhs = new LinkedHashSet<>​(List.of(3,​ 1, 2, 1)); 
 +        System.out.println("​LinkedHashSet:​ " + lhs); // [3, 1, 2] 
 + 
 +        // 3) TreeSet - comparator: lungime, apoi lexicografic 
 +        SortedSet<​String>​ good = new TreeSet<>​( 
 +                Comparator.comparingInt(String::​length) 
 +                          .thenComparing(Comparator.naturalOrder()) 
 +        ); 
 +        good.addAll(List.of("​aa",​ "​b",​ "​bb"​));​ 
 +        System.out.println("​TreeSet ok: " + good); // [b, aa, bb] 
 + 
 +        // Comparator problematic:​ compară DOAR lungimea -> unele elemente sunt excluse 
 +        SortedSet<​String>​ bad = new TreeSet<>​(Comparator.comparingInt(String::​length));​ 
 +        bad.addAll(List.of("​aa",​ "​bb"​));​ // "​bb"​ e ignorat: compare("​aa","​bb"​) == 0 
 +        System.out.println("​TreeSet problematic:​ " + bad); // [aa] 
 +    } 
 +
 +</​code>​ 
 + 
 + 
 +== 1.4 Dicționare (Map și SortedMap) == 
 + 
 +**Map** descrie structuri care asociază fiecărei **chei** o **valoare**:​ 
 + 
 +  * **cheile sunt unice**; 
 +  * valorile pot fi duplicate. 
 + 
 +Ierarhia **Map** este separată de //​Collection//​. Operații tipice: 
 +  * inserare: //put(k, v)//; 
 +  * citire: //get(k)//, //​getOrDefault(k,​ valoareImplicita)//;​ 
 +  * test de apartenență:​ //​containsKey//,​ //​containsValue//;​ 
 +  * eliminare: //​remove(k)//;​ 
 +  * parcurgere: //​entrySet()//,​ //​keySet()//,​ //​values()//​. 
 + 
 +În practică, cele mai folosite implementări sunt: 
 + 
 +  * **HashMap** - rapid, fără ordine de iterare; permite o cheie //null// și valori //null//; 
 +  * **LinkedHashMap** - ca //​HashMap//,​ dar păstrează ordinea inserării;​ 
 +  * **TreeMap** - menține cheile **ordonate** (natural sau prin //​Comparator//​);​ nu acceptă chei //null//; 
 +  * **Hashtable** - tip vechi; se preferă //HashMap// sau //​ConcurrentHashMap//​. 
 + 
 +**SortedMap** este un Map cu chei păstrate în **ordine crescătoare**;​ implementarea clasică este **TreeMap**. 
 + 
 +<code java> 
 +import java.util.*;​ 
 + 
 +class MiniMapDemo { 
 +    public static void main(String[] args) { 
 +        // 1) HashMap - fără ordine 
 +        Map<​String,​ Integer> freq = new HashMap<>​();​ 
 +        for (String w : List.of("​ana",​ "​are",​ "​ana",​ "​mere"​)) { 
 +            freq.merge(w,​ 1, Integer::​sum);​ // new = 1, altfel +1 
 +        } 
 +        System.out.println("​HashMap (fara ordine): " + freq); 
 +        System.out.println("​getOrDefault('​banane',​ 0) = " 
 +            + freq.getOrDefault("​banane",​ 0)); 
 + 
 +        // 2) LinkedHashMap - păstrează ordinea inserării 
 +        Map<​Integer,​ String> lhm = new LinkedHashMap<>​();​ 
 +        lhm.put(2, "​B"​);​ 
 +        lhm.put(1, "​A"​);​ 
 +        lhm.put(3, "​C"​);​ 
 +        System.out.println("​LinkedHashMap (ordine inserare): " + lhm.keySet());​ // [2, 1, 3] 
 + 
 +        // 3) TreeMap - chei ordonate (natural) 
 +        Map<​String,​ Integer> sorted = new TreeMap<>​(freq);​ // sortează după cheia String 
 +        System.out.println("​TreeMap (chei ordonate): " + sorted); 
 + 
 +        // 4) Parcurgere eficientă cu entrySet() 
 +        for (Map.Entry<​String,​ Integer> e : sorted.entrySet()) { 
 +            System.out.println(e.getKey() + " => " + e.getValue());​ 
 +        } 
 +    } 
 +
 +</​code>​ 
 + 
 +=== 2. Iteratori și enumerări === 
 + 
 +Enumerările și iteratorii descriu modalități de **parcurgere secvențială** a unei colecții. În Java, parcurgerea se face în principal cu: 
 + 
 +  * **Iterator** (și pentru liste, //​ListIterator//​),​ 
 +  * sintaxa **for-each**:​ //for (T e : colectie) { ... }//. 
 + 
 +== 2.1 Enumeration == 
 + 
 +**Enumeration** este o interfață veche pentru parcurgere. O mai întâlnim la //Vector// sau o putem obține din orice colecție prin //​Collections.enumeration(...)//​. În cod modern, se preferă //​Iterator//​. 
 + 
 +<code java> 
 +import java.util.*;​ 
 + 
 +class DemoEnumeration { 
 +    public static void main(String[] args) { 
 +        List<​Integer>​ list = List.of(3, 7, 0, 5); 
 +        Enumeration<​Integer>​ en = Collections.enumeration(list);​ // din orice Collection 
 + 
 +        while (en.hasMoreElements()) { 
 +            int x = en.nextElement();​ // Integer, nu Object (datorită generics) 
 +            System.out.println(x);​ 
 +        } 
 +    } 
 + 
 +}  
 +</​code>​ 
 + 
 + 
 +== 2.2 Iterator == 
 + 
 +**Iterator** oferă metodele: 
 +  * **hasNext()** - mai există elemente?;​ 
 +  * **next()** - returnează elementul următor; 
 +  * **remove()** - șterge ultimul element returnat de next(). 
 + 
 +<note important>​ 
 +Dacă modificați colecția în timpul parcurgerii,​ folosiți **iterator.remove()** (sau, mai simplu, //​removeIf(...)//​ pe colecție). ​  
 +</​note>​ 
 + 
 +<code java> 
 +import java.util.*;​ 
 + 
 +class DemoIterator { 
 +    public static void main(String[] args) { 
 +        List<​String>​ l = new ArrayList<>​(List.of("​ana",​ "​bad",​ "​ion",​ "​bogdan"​));​ 
 + 
 +        // Variantă modernă: removeIf 
 +        l.removeIf(s -> s.length() == 4); // șterge elementele cu 4 litere 
 + 
 +        // Echivalent cu iterator.remove() 
 +        Iterator<​String>​ it = l.iterator();​ 
 +        while (it.hasNext()) { 
 +            String s = it.next();​ 
 +            if (s.startsWith("​b"​)) it.remove();​ // sigur 
 +        } 
 + 
 +        System.out.println(l);​ 
 +    } 
 +
 +</​code>​ 
 + 
 +== 2.3 ListIterator (liste, ambele sensuri) == 
 + 
 +//​ListIterator//​ extinde Iterator și oferă în plus: 
 + 
 +  * navigare înapoi: //​previous()//;​ 
 +  * poziții: //​nextIndex()//,​ //​previousIndex()//;​ 
 +  * inserare: //​add(...)//;​ 
 +  * înlocuire: //​set(...)//​. 
 + 
 +Este util când trebuie să modificați lista "pe loc" sau să o parcurgeți bidirecțional. 
 + 
 +<code java> 
 +import java.util.*;​ 
 + 
 +class DemoListIterator { 
 +    public static void main(String[] args) { 
 +        List<​Integer>​ l = new ArrayList<>​(List.of(0,​ 1, 2, 0, 3)); 
 + 
 +        // 1) Înlocuire „pe loc”: 0 -> 10 
 +        ListIterator<​Integer>​ it = l.listIterator();​ 
 +        while (it.hasNext()) { 
 +            if (it.next() == 0) it.set(10);​ 
 +        } 
 + 
 +        // 2) Inserare după 1 
 +        ListIterator<​Integer>​ it2 = l.listIterator();​ 
 +        while (it2.hasNext()) { 
 +            if (it2.next() == 1) {  // elementul curent 1; cursorul este după 1 (între 1 și 2) 
 +                it2.add(99); ​       // inserează între 1 și 2 
 +                break; 
 +            } 
 +        } 
 + 
 +        System.out.println(l);​ // [10, 1, 99, 2, 10, 3] 
 +    } 
 +
 +</​code>​ 
 + 
 +<note warning>​ 
 +Dacă parametrizăm colecția/​iteratorul (ex. //​List<​String>//,​ //​Iterator<​String>//​),​ metodele next()/​previous() întorc direct **tipul elementului** și nu mai avem nevoie de cast.   
 + 
 +Dacă folosim raw types (ex. //List//, //​Iterator//​),​ next()/​previous() întorc **Object** și conversia devine responsabilitatea programatorului - cu risc de //​ClassCastException//​ la rulare. </​note>​ 
 + 
 +<code java> 
 +import java.util.*;​ 
 + 
 +class ObservatieIterator { 
 +    public static void main(String[] args) { 
 +        // 1) Parametrizat (recomandat):​ fără cast, sigur 
 +        List<​String>​ l = new ArrayList<>​(List.of("​ana",​ "​ion"​));​ 
 +        Iterator<​String>​ it = l.iterator();​ 
 +        String s1 = it.next(); // String, nu Object 
 +        ListIterator<​String>​ li = l.listIterator(l.size());​ 
 +        String last = li.previous();​ // tot String 
 +        System.out.println("​OK (generic): " + s1 + ", " + last); 
 + 
 +        // 2) Neparametrizat (raw type): next()/​previous() -> Object, necesită cast 
 +        List raw = new ArrayList();​ // WARNING: unchecked/​raw type 
 +        raw.add("​text"​);​ // compilează 
 +        raw.add(10); ​    // compilează (amestec de tipuri!) 
 +        Iterator itr = raw.iterator();​ // WARNING: raw 
 +        Object o1 = itr.next(); // "​text"​ ca Object 
 +        Object o2 = itr.next(); // 10 ca Object 
 + 
 +        // Castul e responsabilitatea ta; poate eșua la rulare: 
 +        try { 
 +            String s2 = (String) o2; // ClassCastException (Integer -> String) 
 +            System.out.println(s2);​ 
 +        } catch (ClassCastException ex) { 
 +            System.out.println("​Eroare la rulare (raw type): " + ex); 
 +        } 
 +    } 
 +
 +</​code>​ 
 + 
 +=== 3. Genericitate (generics) === 
 + 
 +Fără **generics**,​ o colecție **raw** acceptă obiecte de orice fel, iar la citire trebuie să facem conversii (//cast//). Codul devine greu de urmărit, iar amestecul de tipuri poate produce ușor //​ClassCastException//​ la rulare. 
 + 
 +Genericitatea rezolvă exact aceste probleme: 
 +  * declarăm de la început **tipul elementelor**;​ 
 +  * compilatorul verifică și **interzice** inserarea altor tipuri. 
 + 
 +<code java> 
 +List<​Integer>​ list = new ArrayList<>​();​ // parametrizare:​ lista conține DOAR Integer 
 +list.add(5);​ 
 +list.add(7);​ 
 + 
 +int x = list.iterator().next();​ // fără cast; auto-unboxing (Integer -> int) 
 +int y = list.get(1); ​           // tot fără cast 
 + 
 +// list.add("​Text"​);​ // eroare de compilare: tip incompatibil 
 +</​code>​ 
 + 
 +<note warning>​ 
 +Dacă aveți un caz real în care elementele pot fi de mai multe tipuri, **NU** reveniți la raw types. Folosiți:​ 
 +  * **List<​Object>​** și verificați cu `instanceof` înainte de cast,   
 +  * sau proiectați o ierarhie comună (o interfață,​ o clasă părinte) și parametrizați lista cu acest **supertip**. ​  
 + 
 +În toate celelalte situații folosiți colecții parametrizate (//​List<​Student>//,​ //​Map<​String,​ Integer>//​) pentru **siguranță și claritate**. </​note>​ 
 + 
 + 
 +=== 4. equals() vs hashCode() === 
 + 
 +Metoda **equals(Object)** stabilește **egalitatea logică** dintre două instanțe. Definiția egalității aparține modelului de date (ex.: doi studenți pot fi considerați egali prin CNP, sau prin combinație de câmpuri). 
 + 
 +Metoda **hashCode()** returnează un **rezumat numeric** (int) al obiectului. Colecțiile pe bază de dispersie (//​HashSet//,​ //​HashMap//​) folosesc acest rezumat pentru localizare rapidă. 
 + 
 +<note important>​ 
 +  * Dacă două obiecte sunt **egale** prin //equals//, atunci **trebuie** să aibă același //​hashCode()//​. 
 +</​note> ​  
 + 
 +În **HashSet** și **HashMap**,​ operațiile de apartenență și unicitate funcționează astfel: 
 + 
 +  - colecția calculează **hashCode()** și alege locul elementului;​ 
 +  - confirmă prezența prin **equals()**. 
 + 
 +<code java> 
 +import java.util.*;​ 
 + 
 +class EqualsHashDemo { 
 + 
 +    // Varianta corectă: equals și hashCode folosesc ACELEAȘI câmpuri 
 +    static final class GoodStudent { 
 +        private final String id; 
 +        GoodStudent(String id) { this.id = id; } 
 + 
 +        @Override 
 +        public boolean equals(Object o) { 
 +            if (this == o) return true; 
 +            if (!(o instanceof GoodStudent g)) return false; 
 +            return Objects.equals(id,​ g.id); 
 +        } 
 + 
 +        @Override 
 +        public int hashCode() { 
 +            return Objects.hash(id);​ 
 +        } 
 +    } 
 + 
 +    // Varianta greșită: equals suprascris, hashCode NU 
 +    static final class BadStudent { 
 +        private final String id; 
 +        BadStudent(String id) { this.id = id; } 
 + 
 +        @Override 
 +        public boolean equals(Object o) { 
 +            if (this == o) return true; 
 +            if (!(o instanceof BadStudent b)) return false; 
 +            return Objects.equals(id,​ b.id); 
 +        } 
 +        // (fără hashCode) -> folosește Object.hashCode(),​ diferit pentru instanțe diferite 
 +    } 
 + 
 +    public static void main(String[] args) { 
 +        // Caz corect 
 +        GoodStudent a1 = new GoodStudent("​42"​);​ 
 +        GoodStudent a2 = new GoodStudent("​42"​);​ 
 + 
 +        System.out.println("​a1.equals(a2) = " + a1.equals(a2));​ // true 
 +        System.out.println("​a1.hashCode = " + a1.hashCode() 
 +                + " | a2.hashCode = " + a2.hashCode());​ // egale 
 + 
 +        Set<​GoodStudent>​ good = new HashSet<>​();​ 
 +        good.add(a1);​ 
 +        good.add(a2);​ 
 +        System.out.println("​HashSet<​GoodStudent>​.size = " + good.size());​ // 1 
 + 
 +        // Caz greșit 
 +        BadStudent b1 = new BadStudent("​42"​);​ 
 +        BadStudent b2 = new BadStudent("​42"​);​ 
 + 
 +        System.out.println("​b1.equals(b2) = " + b1.equals(b2));​ // true 
 +        System.out.println("​b1.hashCode = " + b1.hashCode() 
 +                + " | b2.hashCode = " + b2.hashCode());​ // diferite 
 + 
 +        Set<​BadStudent>​ bad = new HashSet<>​();​ 
 +        bad.add(b1);​ 
 +        bad.add(b2);​ 
 +        System.out.println("​HashSet<​BadStudent>​.size = " + bad.size());​ // 2 (duplicate) 
 + 
 +        System.out.println("​bad.contains(new BadStudent(\"​42\"​)) = " 
 +                + bad.contains(new BadStudent("​42"​)));​ // false 
 +    } 
 +} 
 +</code>
  
  
  
poo/breviare/breviar-07.1605603537.txt.gz · Last modified: 2020/11/17 10:58 by mihai.nan
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0