Colectii
Colectii
Autoboxing si unboxing sunt facilitati Java ce permit sa facem atribuiri fara o sintaxa
explicita de cast. Java va face cast-ul la rulare.
Observatie: folosirea autoboxing-ului in cicluri trebuie facuta cu grija pentru ca atrage dupa
sine costuri de performanta.
Colectii Java
In Java colectiile inmagazineaza, grupeaza si sorteaza obiecte. Putem implementa interfete si
extinde clase colectie pentru a defini colectii utilizator. JCF (Java Collection Framework) este
o arhitectura ce pune la dispozitie clase si interfete pentru crearea si manipularea colectiilor.
Asadar, JFC contine:
interfete, unele interfete sunt goale si functioneaza ca markere
implementari, ce asigura dezvoltarea colectiilor utilizator
algoritmi, sunt folositi pentru a rezolva anumite probleme cum ar fi sortarea sau
cautarea intr-o colectie. Algoritmii sunt polimorfici.
O colectie este un obiect destinat sa gestioneze un grup de obiecte:
- un obiect din colectie se numeste element
- primitivele nu sunt permise intr-o colectie
Avantajele folosirii JCF:
ofera colectii predefinite cum ar fi multimile, tabelele de distributie si hartile
faciliteaza referirea cu ajutorul interfetelor
reduce efortul de design si implementare
Avem colectii de diferite tipuri ce implementeaza multe structuri de date comune: stive, cozi,
siruri dinamice, tabele de distributie.
Interfetele colectie formeaza o ierarhie. Radacina este formata din Collection. Elementele
unei Collection pot fi sortate sau nu si pot contine duplicari. Nu exista implementari directe
ale acestei interfete. Toate colectiile pot fi traversate folosind sintaxa foreach. Subinterfete
derivate sunt:
Set, este o colectie ce nu poate contine duplicari si poate contine cel mult un element
null. Set-ul nu are index.
o interfata direct derivata din Set este SortedSet in care elementele sunt, in plus,
ordonate natural (dupa codurile caracterelor). TreeSet furnizeaza o implementare
sortata
direct derivata din SortedSet este interfata NavigableSet, care adauga metode de
navigare bidirectionala (crescator sau descrescator) a multimii si returneaza elemente
ce se potrivesc intr-o oarecare masura unui sablon de cautare. Exemplu de folosire a
lui NavigableSet:
public static void main(String args[]) {
//cream o SortedSet ca instanta a unei clase TreeSet
SortedSet<String> s=new TreeSet<>();
//cream un NavigableSet
NavigableSet<String> n=(NavigableSet<String>)s;
//adaugam elemente
n.add("ion");
n.add("Ion");
n.add("Vasile");
n.add("vasile");
n.add("gelu");
System.out.println("afisare in ordine crescatoare");
Iterator<String> a=n.iterator();
while(a.hasNext()){
System.out.println(a.next());
List, direct derivata din Collection, poate contine elemente duplicat. Elementele
sunt stocate intr-o anumita ordine, data de un index intreg. Elementele pot fi inserate
sau sterse de oriunde din lista. Sunt oferite si metode de cautare. Poate contine mai
multe elemente nule. Listei ii este atasat un iterator. Clasa ArrayList reprezinta un sir
ce creste dinamic daca numarul de elemente depaseste dimensiunea initiala.
Queue, direct derivata din Collection, contine metode aditionale pentru inserare,
inspectare sau extragere de elemente. Nu este recomandabil sa se insereze elemente
nule
BlockingQueue, direct derivata din Queue, contine metode aditionale ce ne permit sa
asteptam pina se creaza un spatiu liber in coada inainte de a insera un nou element
BlockingDeque suporta operatii de blocare, precum asteptarea pentru eliberarea unui
spatiu sau asteptarea ca coada sa devina nevida inainte de a extrage un element. Este
thread safe, iar numarul sau de elemente poate fi limitat. Extinde atat Deque cat si
BlockingQueue.
Deque (double ended queue). Permite inserarea si stergerea la oricare capat. Interfata
nu furnizeaza metode pentru acces indexat, dar putem utiliza metode ca
removeFirstOccurence() si removeLastOccurence() pentru a extrage elemente
interioare dintr-o coada dubla. Putem sa o folosim pentru a crea structuri LIFO sau
FIFO. Nu este recomandabil sa inseram elemente nule, pentru ca null este folosit
pentru a evidentia ca coada este vida
in
//metode de consultare
System.out.println("primul element este :" + ad.peekFirst());
System.out.println("ultimul element este :"+ ad.peekLast());
//metode de stergere
System.out.println("stergem primul element :"+ ad.pollFirst());
System.out.println("stergem ultimul element :"+ ad.pollLast());
}
JCF este sustinuta de anumite interfete auxiliare ce se gasesc in pachetul java.util. Aceste
interfete ne permit sa manipulam elementele unei colectii. Acestea sunt:
RandomAccess este o interfata marker folosita de liste pentru a inlesni accesul rapid la
elemente listelor cu acces secvential sau aleator. Implementari ca Vector sau
ArrayList folosesc aceasta interfata
Comparable ce contine metoda compareTo() si permite doar o optiune de sortare
Comparator ne asigura ca o colectie este ordonata folosind o operatie de ordonare
utilizator. Interfata are doua metode compare() (returneza un intreg) si equals()
(returneza un boolean). Ne permite definirea mai multor optiuni de sortare. Este
implementata partial de clasa abstracta Collator.
Iterator permite parcurgerea inainte intr-o colectie. Are metodele next(),
hasNext() si remove(). Iteratorul unifica accesul la colectii
ListIterator este o extensie a Iterator si permite navigarea in ambele directii. Are
metodele add(), remove() si set() pentru manipulare, next() si previous() pentru
parcurgere, nextIndex() si previousIndex() ce returneza indexul si hasNext() si
hasPrevious() pentru a verifica daca mai exista un element dupa respectiv inaintea
elemetului specificat
Interfata List este implementata de clasele ArrayList, LinkedList si Vector. Metodele
interfetei sunt:
add(element), add(index,element) adauga elementul specificat la sfarsitul listei
sau la un index specificat.
remove(element), remove(index,element) sterge prima aparitie a elementului
specificat sau de la un index specificat. Stergerea determina mutarea spre stanga a
elementelor listei
size()returneaza numarul elemetelor din lista.
System.out.println("Unsupported operation");
} catch (ClassCastException b) {
System.out.println("Class cast");
} catch (NullPointerException n) {
System.out.println("Null pointer");
} catch (IllegalArgumentException t) {
System.out.println("Illegal argument");
}
}
private static boolean removeName(String nume) {
if (checkName(nume))
// indeparteaza un element din lista
return (listaNume.remove(nume));
else
return false;
}
// utilitar pentru obtinerea unui nume de la intrare
private static String getName() {
String name = "";
try {
System.out.print("Nume: ");
name = query.readLine();
} catch (IOException e) {
System.out.println("Invalid name entry");
}
return name;
}
private static void printCommands() {
System.out.println("1: numara cuvinte");
System.out.println("2: sorteaza cuvinte");
System.out.println("3: cauta cuvant");
System.out.println("4: insereaza cuvant");
System.out.println("5: sterge cuvant");
System.out.println("6: afiseaza lista de optiuni");
System.out.println("0: Exit");
}
public static void main(String args[]) {
boolean gata = true;
printCommands();
while (gata) {
try {
System.out.print("Comanda: ");
int argType = Integer.parseInt(query.readLine());
switch (argType) {
case 0: {
gata = false;
break;
}
case 1: {
getWordCount();
break;
}
case 2: {
outputSortedList();
e.getMessage());
break;
}
case 3: {
checkName(getName());
break;
}
case 4: {
insertName(getName());
break;
}
case 5: {
removeName(getName());
break;
}
case 6: {
printCommands();
break;
}
default: {
System.out.println("Comanda invalida");
break;
}
}
} catch (Exception e) {
System.out.println("Operatie invalida, programul va iesi" +
}
} // while
} // main
} // class
System.exit(0);
static
static
static
static
static
static
Collection<String> c = list;
Collection<String> subList = list.subList(1, 8);
// Copy of the sublist:
Collection<String> c2 = new ArrayList<String>(subList);
try {
c.retainAll(c2);
} catch (Exception e) {
System.out.println("retainAll(): " + e);
}
try {
c.removeAll(c2);
} catch (Exception e) {
System.out.println("removeAll(): " + e);
}
try {
c.clear();
} catch (Exception e) {
System.out.println("clear(): " + e);
}
try {
c.add("X");
} catch (Exception e) {
System.out.println("add(): " + e);
}
try {
c.addAll(c2);
} catch (Exception e) {
System.out.println("addAll(): " + e);
}
try {
c.remove("C");
} catch (Exception e) {
}
// The List.set() method modifies the value but
// doesnt change the size of the data structure:
try {
list.set(0, "X");
} catch (Exception e) {
System.out.println("List.set(): " + e);
}
}
public
public
public
public
public
public
static
static
static
static
static
static
public
type);
public
public
public
public
type);
public
type);
ConcurrentHashMap,
iterator()
AbstractSet,
o
o
o
Metoda hashCode()
Este membra a clasei Object si este folosita pentru a genera o valoare intreaga pentru orice
obiect. Fiecare obiect genereaza si inmagazineaza o unica valoare hashcode pe post de cheie.
Sintaxa metodei folosita pentru asa ceva este:
public int hashCode(Object);
si ofera suport pentru implementarile Hashtable
si HashMap.
Codul unic al unui obiect este determinat de datele continute in obiect. Daca datele continute
in doua obiecte sunt egale atunci valoarea hashcode-ului este acelasi, adica daca
ob1.equals(ob2) atunci ob1.hashCode()==ob2.hashCode().
Putem invoca metoda hashCode() din obiecte ce implementeaza interfata Collection.
Pentru aceasta trebuie sa ne asiguram ca clasele ce suprascriu Object.equals() suprascriu si
Object.hashCode(). Conform contractului daca doua obiecte sunt egale via equals()
trebuie sa aiba acelasi hashCode(). Daca metoda este invocata de mai multe ori din acelasi
obiect ea va produce acelasi intreg pe toata durata aplicatiei.
Algoritmi folositi in gestionarea colectiilor
Metodele colectiilor, care sunt polimorfice, cuprind utilitatile predefinite oferite de JDK.
Colectiile au o ordine naturala predefinita (data de codificarea ASCII sau Unicode), aceasta
ordine poate fi modificata de utilizator. Metodele ce implica compararea sunt in general
supraincarcate. O prima varianta de supraincarcare are ca argument o lista sau o colectie in
timp ce a doua are pe linga acest argument inca unul, un Comparator.
Pentru a sorta elementele unei liste toate elementele listei treebuie sa implementeze interfata
Comparable. Apelul lui sort() sorteaza elementele in ordine naturala, dar putem defini un
Comparator pentru a modifica aceasta ordine. Avem doua forme ale metodei sort:
Valoarea returnata este mai mare sau egala cu zero, reprezentand indexul cheii, daca cheia
este gasita sau un rezultat negativ, altfel.
Avem trei algoritmi cu ajutorul carora manipulam datele unei liste.
public static <T> void fill(List<? super T> list, T obj), ceea ce
determina initializarea tuturor elementelor listei cu valoarea celui de-al doilea
parametru
public static void reverse(List<?> list), rearanjeaza in ordine inversa
elementele listei. Ruleaza in timp liniar si arunca o
UnsupportedOperationException daca lista nu suporta setari
public static <T> void copy(List<? super T> dest, List<? extends T>
src), suprascrie o lista destinatie cu toate elementele dintr-o lista sursa
4. Fie un magazin de tricouri, il vom numi Dukes Choice. Tricourile (id, descriere,
culoare, marime, numar bucati) intra (se achizitioneaza) sau ies (se vand din magazin).
Dorim sa facem un inventar al tricourilor si sa tiparim la consola raportul rezultat,
dupa un numar de tranzactii (id tricou, tip tranzactie, numar bucati tranzactionate).
Dorim doua rapoarte: unul in ordinea crescatoare a numarului de bucati si altul in
ordinea alfabetica a descrierii.