Sunteți pe pagina 1din 31

Structuri de Date în Java (VI)

● Interfaţa Map
● Metodele caracteristice ale Map

● Pericolele modificării cheilor

● Prevenirea alterării cheii:

● Modificarea copiei

● Chei nemodificabile

● Proxy-uri nemodificabile pentru chei

● Îngheţarea cheilor

● Comparare şi sortare

● Interfaţa Comparable

● Interfaţa Comparator

● Set-uri sortate

● Stive. Cozi

1
Interfaţa Map

●Realizează maparea între un set de chei şi un set de


valori – perechi de tip (key, value)

●Pentru fiecare obiect cheie avem un obiect valoare


corespondent

● Este în esenţă un instrument de tip “lookup”

● Cheile trebuie să fie unice, însă valorile nu


2
Atenţie: Map nu este o Collection

● Map nu suportă:
● boolean add (Ceva c);

● boolean contains (Object obj);

● Însă suportă:
● boolean put (TipCheie key, TipValue val);

● boolean containsKey (TipCheie key);

● boolean containsValue (TipValue val);

3
Exemplu de folosire a lui Map
Map<String, String> dns = new HashMap<String, String> ();

dns.put ("vega.unitbv.ro", "192.168.1.1");

System.out.println (dns.get ("vega.unitbv.ro"));


System.out.println (dns.containsKey ("vega.unitbv.ro"));
System.out.println (dns.containsValue ("192.168.1.1"));

dns.remove ("vega.unitbv.ro");

System.out.println (dns.containsValue ("192.168.1.1"));

// “192.168.1.1”, true, true, false


4
Alte metode utile
● keySet() - returnează un Set cu toate cheile

● values() - returnează o Collection cu toate valorile

● entrySet() - returneză un set de perechi (key,value)


● fiecare pereche este un obiect Map.Entry

● Map.Entry suportă getKey, getValue, setValue

● orice schimbare în Map se reflectă în Set

5
Pericolele modificării cheilor

● O cheie trebuie să rămână egală cu ceea ce a fost


înainte (în sensul metodei equals)

● Seamănă cu situaţia de la Set-uri

●Dacă o cheie se schimbă, ea împreună cu valoarea


asociată vor fi “pierdute”

6
Folosire incorectă
Name daniela = new Name ("Daniela", "Corboteanu");
Map<Name, String> catalog = new HashMap<Name, String> ();
catalog.put (daniela, "0740-123-456");

System.out.println (catalog.get (daniela));

daniela.first = "Ionel";

System.out.println (catalog.get (daniela));

catalog.put (new Name ("Daniela", "Corboteanu"), "0740-555-123");


daniela.first = "Daniela";

System.out.println (catalog.get (daniela));


7
Două răspunsuri

● Răspunsul corect:
// 0740-123-456, null, 0740-555-123

● Răspunsul şi mai corect:


● Nu contează pentru că nu ar trebui să facem

acest lucru
● Comportare impredictiblă

8
Cum să prevenim modificarea cheii?

● Dorim să putem modifica un obiect din Map

● Dar obiectele cu chei modificabile sunt periculoase

9
Copierea cheii

Name daniela = new Name (“Daniela”, “Corboteanu”);


Name copy = new Name (daniela.first, daniela.last);
map.put (copy, “0740-555-123”);

● Acum schimbările în obiectul daniela nu zăpăcesc map-ul

● Dar cheile în sine tot pot fi modificate:

for (Name name : map.keySet ()) {


name.first = “ am buşit cheia”; // n-am rezolvat nimic
}

10
Facem cheile nemodificabile
public class Name {
public final String first;
public final String last;
public Name (String first, String last) {
this.first = first;
this.last = last;
}
public boolean equals (Object o) {
return (o instanceof Name &&
((Name) o).first.equals (this.first) &&
((Name) o).last.equals (this.last));
}
}
11
Proxy-uri nemodificabile pentru chei

Map<String, String> dir = new HashMap<String, String> ();


Name daniela = new Name (“Daniela”, “Corboteanu”);
String key = daniela.first + “,” + daniela.last;

catalog.put (key, “0740-555-123”);

● String-urile sunt nemodificabile, deci Map-ul va fi protejat

12
Noţiunea de proxy

“Un proxy, în forma sa cea mai generală, este o


clasă funcţionînd ca o interfaţă către altceva. Acel
altceva poate fi orice: o conexiune de reţea, un
obiect de dimensiune mare în memorie, un fişier sau
orice altă resursă care este scumpă de folosit sau
imposibil de duplicat.”
(Wikipedia)

13
“Îngheţarea” cheilor
public class Name {
private String first; // nemodificabile din afara clasei
private String last;
private boolean frozen = false;
// …

public void setFirst (String s) { // metodă mutator controlabilă


if (!frozen) first = s;
}
// … la fel pentru setLast

public void freeze () {


frozen = true;
}
}
14
Rezumat: modificarea cheilor

● Fiecare abordare vine cu anumite dezavantaje


● Pentru fiecare situaţie alegem abordarea cea mai simplă şi

mai la îndemână pe principiul că ce e simpu, bine


structurat, e previzibil şi deci uşor de depanat
● Dacă o cheie nu poate fi niciodată modificată, atunci nu

vom avea niciodată probleme cu ea


● Nu scrieţi o implementare pe care nu o înţelegeţi deplin

decât ca un ultim refugiu


● Dacă ni se pare complicat de scris înseamnă că nu ne-am

gândit îndeajuns de mult la problemă

15
Comparare şi sortare

●Folosite pentru a decide, între două obiecte, dacă


unul este mai mare decât celălalt

● (a.compareTo (b)) trebuie să genereze:


● < 0 dacă a < b

● = 0 dacă a = b

● > 0 dacă a > b

16
Exemplu de comparare

Integer one = 1;
System.out.println (one.compareTo (3));
System.out.println (one.compareTo (-50));

String frank = “Frank”;


System.out.println (frank.compareTo (“Booth”));
System.out.println (frank.compareTo (“Hopper”));

// -1, 1, 4, -2
17
Sortarea alfabetică

List<String> names = new ArrayList<String> ();


names.add (“Sailor”);
names.add (“Lula”);
names.add (“Bobby”);
names.add (“Santos”);
names.add (“Dell”);

Collections.sort (names);
// names: [ “Bobby”, “Dell”, “Lula”, “Sailor”, “Santos” ]
18
Interfaţa Comparable

●Putem compara String-uri pentru că ele


implementează interfaţa Comparable

●Altfel spus, String-urile definesc o “ordine


naturală”

●Pentru a face clasa Ceva comparabilă, trebuie să


implementăm:
● int compareTo (Ceva c);

19
Name-urile devin comparabile

public class Name implements Comparable<Name> {


// …
public int compareTo (Name o) {
int compare = this.last.compareTo (o.last);
if (compare != 0)
return compare;
else
return this.first.compareTo (o.first);
}
}

20
Exemplu de listă sortată de Name-uri
List<Name> names = new ArrayList<Name> ();
names.add (new Name ("Nicolas", "Cage"));
names.add (new Name ("Laura", "Dern"));
names.add (new Name ("Harry", "Stanton"));
names.add (new Name ("Diane", "Ladd"));
names.add (new Name ("William", "Morgan"));
names.add (new Name (“Dirty”, "Glover"));

System.out.println (names);
Collections.sort (names);
System.out.println (names);

// [ Nicolas Cage, Laura Dern, Dirty Glover, Diane Ladd,


// William Morgan, Harry Stanton ]
21
Interfaţa Comparator

●Pentru a crea mai multe ordini de sortare pentru un


anumit tip, vom defini clase Comparator

●Un Comparator primeşte două obiecte şi decide


care este mai mare

● Pentru tipul Ceva, un Comparator<Ceva> are:


● int compare (Ceva o1, Ceva o2);

22
Un Comparator după prenume

public class FirstNameFirst implements Comparator<Name> {


public int compare (Name n1, Name n2) {
int ret = n1.first.compareTo (n2.first);
if (ret != 0)
return ret;
else
return n1.last.compareTo (n2.last);
}
}

● Atenţie, compararea se face altfel decât în cazul Comparable

23
Exemplu de Comparator

List<Name> names = new ArrayList<Name> ();


// ..
Comparator<Name> first = new FirstNameFirst ();
Collections.sort (names, first);
System.out.println (names);

// [ Diane Ladd, Dirty Glover, Harry Stanton, Laura Dern,


// Nicolas Cage, William Morgan ]

● Sortarea se face folosind comparatorul tocmai creat

24
Seturi sortate
● TreeSet – o colecţie de obiecte menţinută mereu sortată
● Fie Object-urile din TreeSet trebuie să implementeze

Comparable
● Sau se furnizează un obiect Comparator la crearea lui

TreeSet

SortedSet<Name> names = new TreeSet<Name> (new FirstNameFirst ());


names.add (new Name ("Laura", "Dern"));
names.add (new Name ("Harry", "Stanton"));
names.add (new Name ("Diane", "Ladd"));
System.out.println(names);
// [ Diane Ladd, Harry Stanton, Laura Dern]
25
Stivă (stack)
● Structură de date bazată pe principiul LIFO (Last
In First Out), în care accesul la elemente se face
numai pe la un singur capăt denumit vârf

● Se scoate întotdeauna
elementul de deasupra

● Se pune peste elementul


de deasupra

26
Clasa Stack

● Implementează interfaţa Collection


● Metodele clasei Stack<E>:

● boolean empty ()

● E peek () - inspectează fără ştergere

● E pop () - scoatere cu ştergere

● E push (E e) - introducere

● int search (Object o) – adâncimea lui o în stivă

● Se aruncă EmptyStackException dacă se face pop

sau peek pe o stivă goală


27
O propoziţie întoarsă pe dos
String line = new String ("epurasul usa rupe");
Stack<Character> sc = new Stack<Character> ();
for (int i = 0 ; i < line.length () ; i ++)
sc.push (line.charAt (i));

String reverse = new String ();


while (sc.size () > 0)
reverse += sc.pop ();

System.out.println (reverse);

// “epur asu lusarupe”


28
Coadă (queue)
●O colecţie de elemente aşezate în ordine pentru
care adăugarea se face întotdeauna la sfârşit iar
extragerea se face de la început

● Principiul FIFO
(First In
First Out)

remove add

29
Clasa LinkedList
● Implementează interfeţele Collection şi Queue
● Metodele interfeţei Queue<E>:

● boolean add (E e) – adăugare la sfârşit

● E element () - inspecarea începutului

● boolean offer (E e) – adăugare fără aruncare excepţie

● E peek () - inspectare fără aruncare excepţie

● E poll () - obţinerea capătului, fără aruncare excepţie

● E remove () - ştergerea capătului

● Se aruncă NoSuchElementException dacă coada este

goală şi se încearcă extragerea unui element din ea (element,


peek, remove)
30
Un palindrom
String line = "copac";
Stack<Character> sc = new Stack<Character> ();
LinkedList<Character> llc = new LinkedList<Character> ();
for (int i = 0 ; i < line.length () ; i ++) {
sc.push (line.charAt (i));
llc.add (line.charAt(i));
}
String palindrom = new String ();

while (llc.size() > 0)


palindrom += llc.remove ();
while (sc.size () > 0)
palindrom += sc.pop ();
System.out.println (palindrom);

// “copaccapoc”
31

S-ar putea să vă placă și