Sunteți pe pagina 1din 55

Proiectarea aplicațiilor orientate

obiect
Curs 10 – fire de execuție, colecții

J
J Acest curs
› Thread pools
› Sincronizarea firelor de execuție
› Colecții
J Thread pool
› Grup de fire de execuție preinstanțiate, inactive, gata să fie lansate în
execuție.
› Se preferă utilizarea unui/unor thread pool atunci când sunt multe fire
de execuție utilizate în mod frecvent
› Implementarea variază de la un limbaj de programare la altul dar în
genere sunt necesare următoarele:
– Un mod de creare a firelor de execuție și reținerea lor în starea inactivă.
– Un container pentru stocarea firelor de execuție create (de obicei o coadă simplă/cu
priorități pentru a adăuga și elimina)
– Interfață standard pentru task-uri
› La crearea unui thread pool sunt instanțiate un număr de fire de execuție
pentru a le pune la dispoziție. În caz de necesitate pot fi adaugate și
altele noi.
J Thread pool
› Când unui pool îi este trimis un task, se preia un fir de execuție din
container sau așteaptă unul să devină disponibil și îi transmite task-ul
spre execuție
› Firul de execuție, se va activa și își va continua execuția apelând
metoda execute() a task-ului furnizat.
› Odată ce execuția este completă, firul de execuție se pune automat
în modul sleep() și apoi înapoi în thread pool pentru a fi reutilizat
› Odată ce firul de execuție este deja creat când cererea sosește,
întârzierea introdusă de crearea unui fir de execuție este eliminată,
făcând aplicația mult mai “responsive”
J Thread pool
J Thread pool - Java
› Un thread pool este soluția optimă pentru a organiza un număr mai
mare de fire de execuție ce rulează concurent.
› Java furnizeaza framework-ul Executor centrat în jurul interfeței
Executor, a subinterfeței ExecutorService și clasa
ThreadPoolExecutor ce implementează ambele interfețe.
› Clasa Executors este folosită pentru a executa taskuri într-un thread
pool, iar ExecutorService organizează și controlează taskurile.
› Prin utilizarea Executors, obiectele trebuie doar sa implementeze
Runnable și apoi trimise către executor pentru execuție.
› În acest fel programatorul se poate focusa pe ceea ce un fir de execuție
trebuie să execute lăsând “mecanica” firelor de execuție în seama thread
pool
J Executor
Metodă Scop
void execute (Runnable object) Execută task-ul
void shutdown () Închide executorul, dar permite task-urilor să se finalizeze. Odată
închis, executorul nu acceptă noi taskuri.
List<Runnable> shutdownNow() Închide imediat executorul, chiar dacă mai sunt fire de execuție
nefinalizate în pool. Returnează o listă de taskuri neterminate.
boolean isShutDown() Returnează true dacă executorul a fost închis
boolean isTerminated() Returnează true dacă toate task-urile în pool au fost terminate
ExecutorService Creează un thread pool cu un număr fixat de thread-uri care se
newFixedThreadPool(int execută simultan. Un thread poate fi folosit pentru a executa un alt
numberOfThreads) task după ce task-ul curent se termină. Dacă un thread se încheie
din cauza unei erori, un nou thread va fi creat pentru a-l înlocui
dacă toate thread-urile din pool nu sunt idle și mai sunt task-uri
așteptându-și execuția.
ExecutorService Creează un thread pool ce pornește noi thread-uri la nevoie, dar
newCachedThreadPool() reutilizează thread-urile construite înainte atunci când acestea sunt
disponibile. Un thread din cached pool va fi terminat dacă nu este
folosit timp de 60 de secunde. Cached pool-ul este util pentru
execuția task-urilor scurte.
J Thread pool - Java
public class Main {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.execute(new RunnableTask1());
executor.execute(new RunnableTask2());
executor.execute(new RunnableTask3());
executor.execute(new RunnableTask4());
executor.shutdown();
}
}
› Clasele RunnableTask1, RunnableTask2 și RunnableTask3
implementează interfața Runnable și suprascriu metoda run().
Dacă se folosește:
ExecutorService executor = Executors.newFixedThreadPool(1);

› Atunci cele 3 task-uri vor fi executate secvențial, deoarece este un


singur thread în pool.
J Thread pool - Java
› Dacă se folosește:
ExecutorService executor = Executors.newCachedThreadPool();

› Atunci noi thread-uri vor fi create pentru fiecare task și atfel


toate task-urile se vor executa simultan.
J
J
J
J Sincronizarea firelor de execuție
› O resursă partajată poate fi coruptă dacă este accesată simultan de mai
multe fire de execuție. Această situație se numește race condition în
programele multithread.
› O clasă este thread-safe dacă un obiect al clasei nu cauzează race
condition în prezența mai multor fire de execuție.
› Pentru a evita race condition, trebuie evitată situația în care mai mult de
un fir de execuție execută o anumită secvență de program, numită
regiune critică.
› Se poate folosi cuvântul cheie synchronized asupra unei metode pentru
ca numai un fir de execuție să acceseze metoda la un moment de timp.

public synchronized void methodName (parameters_list)


J Sincronizarea firelor de execuție
› Invocarea unei metode sincronizate a unui obiect obține lock-ul asupra
obiectului
› Invocarea unei metode sincronizate statice obține lock-ul asupra clasei.
Un bloc sincronizat permite obținerea lock-ului asupra oricărui obiect sau
secvență de cod:
synchronized (obj) {
instrucțiuni;
}
› Dacă obiectul este deja locked de alt thread, thred-ul este blocat până
când lock-ul este eliberat.
› Când este obținut lock-ul asupra unui obiect, sunt executate instrucțiunile
din blocul sincronizat și apoi lock-ul este eliberat.
J Sincronizarea firelor de execuție
› Blocurile sincronizate permit sincronizarea unei părți de cod din
metodă și nu a întregii metode.
› Următoarele secvențe sunt echivalente
public synchronized void xMethod() {
// corpul metodei
}

public void xMethod() {


synchronized (this) {
// corpul metodei
}

….
}
Sincronizarea firelor de execuție
J class Counter{
long count = 0;
public synchronized long add(long value){
return this.count += value;
}
}
class CounterThread extends Thread {
String name;
protected Counter counter = null;
public CounterThread(Counter counter, String name) {
this.counter = counter;
this.name = name;
System.out.println("Thread " + name + " created");
}
public void run() {
System.out.println("Thread " + name + " started");
for (int i = 0; i < 100; i++) {
System.out.println(name + ": " + counter.add(1));
}
System.out.println("Thread " + name + " finished");
}
J Sincronizarea firelor de execuție
public class Main {
public static void main(String[] args) {
Counter counter = new Counter();
Thread threadA = new CounterThread(counter);
Thread threadB = new CounterThread(counter);
threadA.start();
threadB.start();
}
} Thread A created … … …
Thread B created A: 194
Thread A started A: 195
Thread B started B: 187
B: 2 B: 196
A: 1 B: 197
B: 3 B: 198
B: 5 B: 199
B: 6 B: 200
A: 4 Thread A finished
… … … Thread B finished
J Sincronizarea firelor de execuție
› Java permite obținerea lock-urilor în mod explicit, ceea ce dă
posibilitatea unui control mai ușor asupra firelor de execuție.
› Un lock este o referinta a interfeței Lock, care definește metodele
pentru obținerea și eliberarea lock-urilor (lock() și unock())
› metoda newCondition(), care returnează un obiect de tipul
Condition, utilizat pentru comunicarea dintre firele de execuție
class Counter{
long count = 0;
private static Lock lock = new ReentrantLock();
public long add(long value){
lock.lock();
return this.count += value;
lock.unlock();
}
}
J Sincronizarea firelor de execuție
› În general, utilizarea blocurilor sau metodelor sincronizate este mai
simplă decât folosirea lock-urilor explicite. Totuși, cele din urmă sunt mai
flexibile și mai utile pentru sincronizarea firelor de execuție cu condițiile.
› Odată ce o condiție este creată, se pot utiliza metodele await(),
signal() și signalAll() pentru comunicarea dintre thread-uri.
› Metoda await() face ca thread-ul curent să aștepte până când o
condiție este semnalată.
› Metoda signal() activează thread-ul în așteptare,
› signalAll() activează toate thread-urile care sunt în așteptare.
› Dacă se apelează await() și nu se invocă apoi signal() sau
signalAll(), atunci acel thread va aștepta la infinit.
J Sincronizarea firelor de execuție
Lock lock = new ReentrantLock();
Condition cond = lock.newCondition();
… … …
cond.await(); // thread-ul curent pus in asteptare
… … …
cond.signal(); // thread-ul curent este activat
… … …
cond.singnalAll(); // toate thread-urile sunt activate

› Un monitor este un obiect cu capabilitate de sincronizare. Doar un


singur thread poate executa la un moment de timp o metodă dintr-un
monitor. Un thread intră pe monitor prin obținerea unui lock asupra lui
și iese prin eliberarea acelui lock. Orice obiect poate fi un monitor.
Obținerea lock-ului se face prin utilizarea cuvântului synchronized pe
o metodă sau un bloc
J
› Semafoarele sunt utilizate pentru a restricționa numărul de
thread-uri ce accesează o resursă partajată.
› Înainte să acceseze resursa, un thread trebuie să obțină permisiune
de la un semafor.
› După ce se încheie lucrul cu resursa, firul de execuție trebuie să
returneze permisiunea înapoi la semafor. Acest lucru se realizează
cu ajutorul metodelor acquire() și release().
J Programare generică
› Metode generice și clasele generice permit parametrizarea tipului de
date referință
› Mod de implementare - TypeErasure
– înlocuiește toți parametri generici cu Object sau SuperClass. Astfel codul obținut
conține doar clase, interfețe și metode ordinare
– inserează type cast dacă este necesar
– genereaza metode “bridge” pentru a păstra polimorfismul în tipurile generice
› În general se folosește Object oriunde este intalnit T
› Compilatorul verifica dacă ceea ce este scris este posibil însă codul
generat conține java.lang.Object
Metode generice
J public class MaximumTest {
public static <T extends Comparable<T>> T maximum(T x, T y, T z) {
T max = x;
if(y.compareTo(max) > 0) {
max = y;
}
if(z.compareTo(max) > 0) {
max = z;
}
return max; Max of 3, 4 and 5 is 5
} Max of 6.6,8.8 and 7.7 is 8.8
} Max of pear, apple and orange is pear
public class Main {
public static void main(String[] args) {
System.out.printf("Max of %d, %d and %d is %d\n", 3, 4, 5,
MaximumTest.maximum( 3, 4, 5 ));
System.out.printf("Max of %.1f,%.1f and %.1f is %.1f\n", 6.6, 8.8, 7.7,
MaximumTest.maximum( 6.6, 8.8, 7.7 ));
System.out.printf("Max of %s, %s and %s is %s\n","pear", "apple",
"orange", MaximumTest.maximum("pear", "apple", "orange"));
}
J Clase generice
class Box<T> {
› Declaratia unei clase generice este asemanatoare celei non-generic
private T t;
cu exceptia
public faptului
void add(T t) ca
{ numele ii este urmat de “type parameter
this.t
section = t;
- <…>”
}
public T get() {
return t;
}
}
public class Main {
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
Box<String> stringBox = new Box<String>();
integerBox.add(new Integer(10));
stringBox.add(new String("Hello World"));
System.out.printf("Integer Value :%d\n\n", integerBox.get());
System.out.printf("String Value :%s\n", stringBox.get());
}
Integer Value :10
}
String Value :Hello World
J Cum ”lucrează” TypeErasure
› Atunci când super class este Object

// Inainte de compilare // Dupa compilare


class GFG<T> { class GFG {
T obj; Object obj;

GFG(T o) { GFG(Object o) {
obj = o; obj = o;
} }
T getob() { Object getob() {
return obj; return obj;
} }
} }
J Cum ”lucrează” TypeErasure
› Atunci când super class este Object

// Inainte de compilare // Dupa compilare


class MyClass<T extends String> { class MyClass {

T str; String str;


MyClass(T o) { MyClass(T o) {
str = o; str = o;
} }
T getob() { String getob() {
return str; return str;
} }
} }
J Colecții
› O structură de date – în programarea orientată pe obiecte, numită
și container - este o colecție de date organizate într-o anumită
manieră.
› O structură de date este în sine o clasă care trebuie să aibă câmpuri
și metode care să asigure inserarea, ștergerea și alte operații.
› Java Collections Framework are două tipuri de structuri de date:
– pentru a stoca o colecție de elemente, numită colecție
– pentru a stoca perechi de tipul cheie-valoare, numită map.
› Java Collections Framework are 3 tipuri de colecții:
– Set stochează elemente distincte (neduplicate).
– List stochează o colecție ordonată de elemente.
– Queue stochează elemente ce respectă proprietatea primul intrat, primul ieșit.
J Arhitectura colecțiilor
› Interfeţe: tipuri abstracte de date ce descriu colecţiile şi permit
utilizarea lor independent de detaliile implementărilor.
› Implementări: implementări concrete ale interfeţelor ce descriu
colecţii (clase); reprezintă tipuri de date reutilizabile.
› Algoritmi polimorifici: metode care efectuează diverse operaţii
utile(căutare, sortare) definite pentru obiecte ce implementează
interfeţele ce descriu colecţii. Aceşti algoritmi se numesc şi
polimorfici deoarece pot fi folosiţi pe implementări diferite ale unei
colecţii, reprezentând elementul de funcţionalitate reutilizabilă.
J Interfeţe ce descriu colecţii
› Collection - modelează o colecţie la nivelul cel mai general, descriind
un grup de obiecte (elementele sale).
› Map - descrie structuri de date de tip cheie – valoare, asociază fiecarui
element o cheie unică, după care poate fi regăsit
J Interfața Collection
› Este rădăcina pentru lucrul cu colecțiile.
› AbstractCollection este o clasă ce furnizează o implementare
parțială a interfeței Collection. Ea implementează toate metodele din
Collection, mai puțin metodele size și iterator. Acestea sunt
implementate în subclasele corespunzătoare. Metodele din interfața
Collection sunt:
J Interfata Collection
Metoda Scop
boolean add (E o) Adaugă un nou element o în colecție
boolean addAll(Collection<? extends E> c) Adaugă elementele colecției c în colecție
void clear() Șterge toate elementele colecției
boolean contains (Object o) Returnează true dacă colecția conține elementul o
boolean containsAll(Collection<?> c) Returnează true dacă această colecție conține toate elementele din c
boolean equals(Object o) Returnează true dacă colecția este identică cu altă colecție o
int hashCode() Returnează codul hash al acestei colecții
boolean isEmpty() Returnează true dacă colecția nu conține elemente
Iterator<E> iterator() Returnează un iterator pentru elementele din colecție
boolean hasNext() Returnează true dacă iteratorul mai are elemente de traversat
E next() Returnează următorul element al iteratorului
void remove() Șterge ultimul element obținut utilizând metoda next()
boolean remove(Object o) Elimină elementul o din colecție
boolean removeAll(Collection<?> c) Elimină toate elementele din c din această colecție
boolean retainAll(Collection<?> c) Păstrează elementele care sunt în c și în această colecție
int size() Returnează numărul de elemente din colecție
Object[] toArray() Returnează un tablou de elemente de tipul Object pentru
elementele din această colecție
J Interfața Set
› Extinde interfața Collection.
› Nu introduce noi metode, ci doar limitează elementele
setului să fie unice.
› AbstractSet este o clasă abstractă care implementează
Set și extinde AbstractCollection.
› Metodele size și iterator nu sunt implementate. Acestea
sunt implementate în subclasele corespunzătoare.
J
J Interfața SortedSet
› mulţime cu elemente sortate.
› ordonarea elementelor se face conform ordinii lor naturale,
sau conform cu ordinea dată de un comparator specificat la
crearea colecţiei
› ordinea este menţinută automat la orice operaţie efectuată
asupra mulţimii.
› pentru orice două obiecte o1, o2 ale colecţiei, apelul
o1.compareTo(o2) (sau comparator.compare(o1, o2), dacă
este folosit un comparator) trebuie să fie valid şi să nu
provoace excepţii
J Interfața SortedSet

public interface SortedSet extends Set {


// Subliste
SortedSet subSet(Object fromElement, Object toElement);
SortedSet headSet(Object toElement);
SortedSet tailSet(Object fromElement);
// Capete
Object first();
Object last();
Comparator comparator();
}
J Interfața TreeSet
› TreeSet implementează SortedSet. Se pot adăuga obiecte în tree
set atâta timp cât pot fi comparate unul cu altul. Există două
modalități de a compara obiectele:
– Cu ajutorul interfeței Comparable. Obiectele pot fi comparate cu ajutorul
metodei compareTo;
– Cu ajutorul unui comparator din interfața Comparator.
Interfața TreeSet
J import java.util.*;
public class TestHashSet {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("Ana");
set.add("Maria");
set.add("Andrei");
set.add("Mihai");
set.add("Ana");
System.out.println(set );
TreeSet<String> treeSet = new TreeSet<String>(set);
System.out.println("Sorted tree set: " + treeSet);
System.out.println("first(): " + treeSet.first());
System.out.println("last(): " + treeSet.last());
System.out.println("headSet(): " + treeSet.headSet("Maria"));
System.out.println("tailSet(): " + treeSet.tailSet("Maria"));
System.out.println("pollFirst(): " + treeSet.pollFirst());
System.out.println("pollLast(): " + treeSet.pollLast());
System.out.println("New tree set: " + treeSet);
}
}
J
› Dacă nu trebuie menținut un set sortat atunci când se introduc elemente,
este indicat a se folosi un hash set deoarece operațiile de adaugare și
eliminare sunt mai mai rapide.
› Se poate crea un sorted set din hash set când este necesar.
› Când se inserează elemente într-un tree set, dar ele nu sunt instanțe
ale Comparable, se poate defini un comparator pentru aceste obiecte.
Pentru aceasta, se poate crea o clasă care implementează interfața
Comparator, cu două metode, compare() și equals().
public int compare (Object o1, Object o2) – returnează o valoare negativă
dacă o1 este mai mic decât o2, o valoare pozitivă dacă o1 este mai mare ca o2 și 0
dacă sunt egale;
public boolean equals (Object o) – returnează true dacă cele două obiecte
sunt identice.
J
import java.util.Comparator;
public class GeometricObjectComparator implements Comparator<GeometricObject> {
public int compare(GeometricObject o1, GeometricObject o2) {
double area1 = o1.getArea();
double area2 = o2.getArea();
if (area1 < area2)
return -1;
else if (area1 == area2)
return 0;
else
return 1;
}
}
J

public class Main {


public static void main(String[] args) {
Set<GeometricObject> set = new TreeSet<GeometricObject>(new
GeometricObjectComparator());
set.add(new Rectangle(4, 5));
set.add(new Circle(40));
set.add(new Circle(40));
for (GeometricObject element: set)
System.out.println("area = " + element.getArea());
}
}
J Interfața List
› liste de elemente indexate.
› pot conține duplicate şi permit un control precis asupra
poziţiei unui element prin intermediul indexului acelui
element.
› există metode pentru acces poziţional, căutare şi iterare
avansată.
› Implementări: ArrayList, LinkedList, Vector, Stack.
J
Metodele din java.util.List<E>
Metoda Scop

J boolean add (int index, E element)


boolean addAll (int index, Collection<?
extends E> c)
Adaugă un nou element la indexul specificat
Adaugă elementele din c în listă începând cu indexul
specificat
E get (int index) Returnează elementul de pe poziția index
int indexOf (Object element) Returnează indexul primei apariții a lui element
int lastIndexOf (Object element) Returnează indexul ultimei apariții a lui element
ListIterator<E> listIterator() Returnează list iteratorul pentru elementele listei
ListIterator<E> listIterator(int startIndex) Returnează list iteratorul pentru elementele listei începând
cu startIndex
E remove (int index) Elimină elementul de pe indexul specificat
E set (int index, E element) Setează elementul la indexul specificat
List<E> subList(int fromIndex, int toIndex) Returnează o sublistă de la fromIndex la subIndex-1

Metodele din java.util.ListIterator<E>


Metoda Scop
void add (E o) Adaugă obiectul o în listă
boolean hasPrevious() Returnează true dacă list iteratorul mai are elemente la o
traversare inversă
int nextIndex() Returnează indexul următorului element
E previous () Returnează elementul anterior în list iterator
int previousIndex() Returnează indexul elementului anterior
void set (E o) Înlocuiește ultimul element returnat de next() sau de last()
cu elementul o
J
› Clasele ArrayList și LinkedList sunt două implementări concrete ale
interfeței List. ArrayList stochează elementele într-un tablou creat
dinamic. Dacă capacitatea tabloului este depășită, un tablou mai mare
este creat și elementele din tabloul curent sunt copiate în noul tablou.
Constructorii lui ArrayList sunt:
– ArrayList() – creează o listă vidă cu capacitate inițială implicită;
– ArrayList(Collection<? extends E> c) – creează un ArrayList dintr-o
colecție existentă;
– ArrayList(int initialCapacity) – creează un ArrayList cu o capacitate
inițială specificată.
J
› LinkedList stochează elementele într-o listă înlănțuită. Are metode
pentru căutarea, inserare și ștergerea de la ambele capete ale listei.
– void addFirst (T o) – adaugă un element la începutul listei;
– void addLast (T o) – adaugă un element la finalul listei;
– T getFirst() – returnează primul element al listei;
– T getLast() – returnează ultimul element al listei;
– T removeFirst() – returnează și șterge primul element al listei;
– T removeLast () – returnează și șterge ultimul element al listei.
public class Main {
public static void main(String[] args) {
List<Integer> arrayList = new ArrayList<Integer>();
J arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
arrayList.add(4);
arrayList.add(5);
System.out.println(arrayList);
LinkedList<Integer> linkedList = new LinkedList<Integer>(arrayList);
linkedList.add(1, 10);
linkedList.removeFirst();
linkedList.removeLast();
ListIterator<Integer> listIterator = linkedList.listIterator();
while (listIterator.hasNext()) {
System.out.print(listIterator.next() + " ");
}
System.out.println();
listIterator = linkedList.listIterator(linkedList.size());
while (listIterator.hasPrevious()) {
System.out.print(listIterator.previous() + " ");
} [1, 2, 3, 4, 5]
} 10 2 3 4
} 4 3 2 10
J Clasele Vector și Stack
› Clasa Vector este la fel ca ArrayList, cu diferența că are metode
sincronizate pentru accesul și modificarea vectorului.
› Metodele sincronizate previn coruperea datelor când un vector este
accesat și modificat de două fire de execuție simultan. Pentru multele
aplicații care nu necesită sincronizare, utilizarea ArrayList-urilor este
mai eficientă și rapidă decât a claselor Vector.
– Stack() – creează o stivă nouă;
– boolean empty() – returnează true dacă stiva este vidă;
– T peek() – returnează elementul de la vârful stivei;
– T pop() – returnează și elimină elementul de la vârful stivei;
– T push (T o) – adaugă elementul o la vârful stivei;
– int search (Object o) – returnează poziția elementului specificat în stivă.
J Cozi și Cozi cu priorități
› O coadă este o structură de tipul first-in, first-out. Într-o coadă cu
priorități, elementelor le sunt atribuite priorități. Când sunt accesate
elementele, elementul cu prioritatea cea mai mare este eliminat primul.
Metodele din interfața java.util.Queue sunt:
– boolean offer (T element) – inserează un element în coadă;
– T poll () – returnează și elimină vârful cozii, sau null dacă coada este vidă;
– T remove () - returnează și elimină vârful cozii, sau aruncă o excepție dacă coada
este vidă;
– T peek () – returnează, dar nu elimină vârful cozii, sau returnează null dacă
coada este vidă;
– T element () – returnează, dar nu elimină vârful cozii, sau aruncă o excepție dacă
coada este vidă.
J
public class Main {
public static void main(String[] args) {
java.util.Queue<String> queue = new java.util.LinkedList<String>();
queue.offer("red");
queue.offer("green");
queue.offer("blue");
while (queue.size() > 0)
System.out.print(queue.remove() + " ");
}
}
J
› Clasa PriorityQueue implementează o coadă cu priorități. Coada cu
priorități ordonează elementele în ordinea lor naturală, utilizând
Comparable. Elementului cu cea mai mică valoare i se asignează
cea mai mare prioritate și astfel este eliminat primul din coadă. Se
poate specifica o ordine, folosind Comparator în constructor:
PriorityQueue(initialCapacity, comparator).
J MAP
› Map este un container care stochează elemente și chei. Cheile pot fi
orice obiecte.
› Map nu poate conține chei duplicate. O cheie, împreună cu valoarea sa,
formează o intrare (entry).Există 3 tipuri de Maps:
– HashMap
– LinkedHashMap
– TreeMap
› Din interfața java.util.Map.Entry avem următoarele metode:
– K getKey() – returnează cheia corespunzătoare entry-ului;
– V getValue() – returnează valoarea corespunzătoare entry-ului;
– void setValue (V value) – înlocuiește valoarea în entry.
J Map
› Interfața SortedMap extinde interfața Map și menține
maparea în ordine ascendentă a cheilor, cu metodele
firstKey() și lastKey() care returnează cea mai mică
și cea mai mare cheie, headMap(key) ce returnează
porțiunea din Map ale cărei chei sunt mai mici decât key și
tailMap(key) ce returnează porțiunea din Map ale cărei
chei sunt mai mari sau egale decât key.
J
› Clasa HashMap este eficientă pentru găsirea unei valori, inserarea sau
ștergerea unei intrări.
› LinkedHashMap extinde HashMap, cu o implementare înlănțuită, ce
asigură ordonarea intrărilor în map.
› Intrările din HashMap nu sunt ordonate, însă intrările din LinkedHashMap
pot fi găsite fie în ordinea în care au fost inserate în map, fie în ordinea
în care au fost ultima dată accesate.
› Clasa TreeMap este eficientă pentru traversarea cheilor în ordine
sortată. Cheile pot fi sortate utilizând interfețele Comparable sau
Comparator.
› Pentru cazul când se implementează interfața Comparator, trebuie
utilizat constructorul TreeMap(Comparator comparator).
J
public class Main {
public static void main(String[] args) {
Map<String, Integer> hashMap = new HashMap<String, Integer>();
hashMap.put("Red", 30);
hashMap.put("Green", 31);
hashMap.put("Blue", 29);
hashMap.put("Yellow", 29);
System.out.println(hashMap);
Map<String, Integer> treeMap = new TreeMap<String, Integer>(hashMap);
System.out.println(treeMap);
Map<String, Integer> linkedHashMap = new LinkedHashMap<String, Integer>();
linkedHashMap.put("Red", 30);
linkedHashMap.put("Green", 31);
linkedHashMap.put("Blue", 29);
linkedHashMap.put("Yellow", 29);
System.out.println(linkedHashMap); {Red=30, Blue=29, Yellow=29, Green=31}
} {Blue=29, Green=31, Red=30, Yellow=29}
} {Red=30, Green=31, Blue=29, Yellow=29}
J Caracteristici comune
› permit elementul null
› sunt serializabile
› au definită metoda clone
› au definită metoda toString
› permit crearea de iteratori
› au atât constructor fără argumente cât şi un constructor care acceptă
ca argument o altă colecţie
› exceptând clasele din arhitectura veche, nu sunt sincronizate.

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