Sveobuhvatna analiza Java okvira kolekcija
"Neću, sačekaj da završim ovu partiju."
"Dobro." slegnem ramenima. "Onda ću ja crtati dijagram strukture okvira kolekcija i čekati te."

"Završio si već, Sanmej?"
"Završila sam davno, Erge, tako sporo crtaš, daj da pogledam kako izgleda."
"Eh, nacrtati jasan dijagram nije lako. Sanmej, gledaj, nije li dobar?"
"Ovaj, zaista je super, brate, baš si temeljan!"
"Hajde da ukratko predstavim."
Java okvir kolekcija se može podeliti u dve velike grane:
①,Collection, uglavnom čine List, Set i Queue:
- List predstavlja uređene, ponavljajuće kolekcije; tipični predstavnici su ArrayList, koji obuhvata dinamički niz, i LinkedList, koji obuhvata povezanu listu;
- Set predstavlja neuređene, neponavljajuće kolekcije; tipični predstavnici su HashSet i TreeSet;
- Queue predstavlja red; tipični predstavnici su dvostruki red ArrayDeque, kao i red prioriteta PriorityQueue.
②,Map, predstavlja kolekciju parova ključ-vrednost; tipični predstavnik je HashMap.
01,List
Odlika List-a je da je uređen pri čuvanju i dohvatanju, može da čuva ponavljajuće elemente i da elementima pristupa preko indeksa.
1)ArrayList
Najpre hajde da vidimo dodavanje, brisanje, izmenu i pretragu za ArrayList, da naučimo kako se koristi.
// kreira kolekciju
ArrayList<String> list = new ArrayList<String>();
// dodaje elemente
list.add("Wang Er");
list.add("Chenmo");
list.add("Chen Qingyang");
// prelazi kroz kolekciju for petljom
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
// prelazi kroz kolekciju for each
for (String s : list) {
System.out.println(s);
}
// briše element
list.remove(1);
// prelazi kroz kolekciju
for (String s : list) {
System.out.println(s);
}
// menja element
list.set(1, "Wang Ergou");
// prelazi kroz kolekciju
for (String s : list) {
System.out.println(s);
}Ukratko o osobinama ArrayList-a, detaljnije će biti reči kasnije.
- ArrayList je implementiran na osnovu niza i podržava slučajan pristup, odnosno elementima se može pristupati direktno preko indeksa;
- Dodavanje i brisanje elemenata s kraja je relativno brzo, dok je dodavanje i brisanje elemenata sa sredine neefikasnije, jer uključuje kopiranje i pomeranje elemenata niza;
- Kada kapacitet unutrašnjeg niza nije dovoljan, automatski se proširuje, pa kada je broj elemenata vrlo veliki, efikasnost je niža.
2)LinkedList
Isto tako, hajde da vidimo dodavanje, brisanje, izmenu i pretragu za LinkedList — gotovo da se ne razlikuje od ArrayList-a.
// kreira kolekciju
LinkedList<String> list = new LinkedList<String>();
// dodaje elemente
list.add("Wang Er");
list.add("Chenmo");
list.add("Chen Qingyang");
// prelazi kroz kolekciju for petljom
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
// prelazi kroz kolekciju for each
for (String s : list) {
System.out.println(s);
}
// briše element
list.remove(1);
// prelazi kroz kolekciju
for (String s : list) {
System.out.println(s);
}
// menja element
list.set(1, "Wang Ergou");
// prelazi kroz kolekciju
for (String s : list) {
System.out.println(s);
}Međutim, LinkedList i ArrayList i dalje se znatno razlikuju, i o tome će biti detaljno reči kasnije.
- LinkedList je implementiran pomoću dvostruko povezane liste, ne podržava slučajan pristup i može se prelaziti samo s jedne strane dok se ne pronađe traženi element;
- Dodavanje i brisanje elemenata na bilo kojoj poziciji je vrlo pogodno, jer je potrebno samo promeniti reference prethodnog i sledećeg čvora, za razliku od ArrayList-a koji zahteva kopiranje i pomeranje elemenata niza;
- Pošto svaki element čuva reference na prethodni i sledeći čvor, zauzima nešto više memorijskog prostora u poređenju sa ArrayList-om.
3)Vector i Stack
Još jedna klasa implementacija List-a je Vector, klasica stare škole, pojavila se ranije od ArrayList-a. ArrayList i Vector su vrlo slični, ali je Vector bezbedan za niti — metodi poput get, set, add imaju ključnu reč synchronized, što dovodi do niže efikasnosti izvršavanja, pa se danas retko koristi.
Neću pisati previše koda, samo ćemo pogledati izvorni kod add metoda i biće jasno.
public synchronized boolean add(E e) {
elementData[elementCount++] = e;
return true;
}Ovakve klase sa sinhronizovanim metodima su predodređene da budu zaboravljene, baš kao što je StringBuilder zamenio StringBuffer. I izvorni kod JDK-a kaže:
Ako vam nije potrebna bezbednost niti, preporučuje se upotreba ArrayList-a umesto Vector-a.

Stack je podklasa klase Vector, u suštini je takođe implementiran dinamičkim nizom, ali dodatno implementira funkciju "prvi ušao, poslednji izašao" (na get, set, add metode su dodati pop "vraća i uklanja element s vrha steka", peek "samo vraća element s vrha steka" itd.), pa se zove stek.
Ispod je izvorni kod ova dva metoda; dodavanje, brisanje, izmenu i pretragu neću pisati, gotovo su isti kao kod ArrayList-a i LinkedList-a.
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
removeElementAt(len - 1);
return obj;
}
public synchronized E peek() {
int len = size();
if (len == 0)
throw new EmptyStackException();
return elementAt(len - 1);
}Međutim, pošto je Stack-ova efikasnost izvršavanja relativno niska (metodi takođe imaju synchronized ključnu reč), zamenjen je dvostrukim redom ArrayDeque (o kom će biti reči u nastavku).
02,Set
Odlika Set-a je da je neuređen pri čuvanju i dohvatanju, ne može da čuva ponavljajuće elemente i ne može da pristupa elementima preko indeksa, što ga na mnogo načina razlikuje od List-a.
1)HashSet
HashSet je zapravo implementiran pomoću HashMap-a, ali je vrednost popunjena jednim fiksnim Object objektom, dok se ključ koristi za operacije. Hajde ukratko da pogledamo njegov izvorni kod.
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
public HashSet() {
map = new HashMap<>();
}
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
}U stvarnom razvoju, HashSet se ne koristi često; na primer, ako nam je potrebno da čuvamo skup elemenata po redosledu, onda su ArrayList i LinkedList možda prikladniji; ako nam je potrebno da čuvamo parove ključ-vrednost i pretražujemo po ključu, onda je HashMap možda prikladniji.
Hajde da iskusimo dodavanje, brisanje, izmenu i pretragu:
// kreira novi HashSet
HashSet<String> set = new HashSet<>();
// dodaje elemente
set.add("Chenmo");
set.add("Wang Er");
set.add("Chen Qingyang");
// ispisuje broj elemenata u HashSet-u
System.out.println("HashSet size: " + set.size()); // output: 3
// proverava da li element postoji u HashSet-u
boolean containsWanger = set.contains("Wang Er");
System.out.println("Does set contain 'Wang Er'? " + containsWanger); // output: true
// briše element
boolean removeWanger = set.remove("Wang Er");
System.out.println("Removed 'Wang Er'? " + removeWanger); // output: true
// menja element, mora prvo obrisati pa dodati
boolean removeChenmo = set.remove("Chenmo");
boolean addBuChenmo = set.add("NeChenmo");
System.out.println("Modified set? " + (removeChenmo && addBuChenmo)); // output: true
// ispisuje HashSet nakon izmene
System.out.println("HashSet after modification: " + set); // output: [Chen Qingyang, NeChenmo]HashSet se uglavnom koristi za uklanjanje duplikata; na primer, ako želimo da izračunamo koliko jedinstvenih reči ima u članku, možemo koristiti HashSet.
// kreira HashSet objekat
HashSet<String> set = new HashSet<>();
// dodaje elemente
set.add("Chenmo");
set.add("Wang Er");
set.add("Chen Qingyang");
set.add("Chenmo");
// ispisuje broj elemenata u HashSet-u
System.out.println("HashSet size: " + set.size()); // output: 3
// prelazi kroz HashSet
for (String s : set) {
System.out.println(s);
}Iz gornjeg primera se vidi da HashSet automatski uklanja duplikate, jer je implementiran pomoću HashMap-a, a ključevi HashMap-a su jedinstveni (hash vrednost), pa će vrednost istog ključa prepisati originalnu vrednost, te je drugi put set.add("Chenmo") prepisao prvi set.add("Chenmo").
Koristio sam HashSet kada sam radio LeetCode zadatak 15: suma tri broja, možete pogledati preko linka.
2)LinkedHashSet
Iako LinkedHashSet nasleđuje HashSet, zapravo je implementiran pomoću LinkedHashMap-a.
Ovo je konstruktor bez argumenata za LinkedHashSet:
public LinkedHashSet() {
super(16, .75f, true);
}super znači da će pozvati jedan konstruktora sa argumentima iz HashSet-a roditeljske klase:
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}Vidite LinkedHashMap, o njemu će biti reči kasnije.
Dobro, hajde da vidimo dodavanje, brisanje, izmenu i pretragu za LinkedHashSet.
LinkedHashSet<String> set = new LinkedHashSet<>();
// dodaje elemente
set.add("Chenmo");
set.add("Wang Er");
set.add("Chen Qingyang");
// briše element
set.remove("Wang Er");
// menja element
set.remove("Chenmo");
set.add("Snaga ćutanja");
// traži element
boolean hasChenQingYang = set.contains("Chen Qingyang");
System.out.println("Da li set sadrži Chen Qingyang? " + hasChenQingYang);U gorenjem kodu, prvo smo kreirali LinkedHashSet objekat, a zatim pomoću add metoda redom dodali tri elementa: Chenmo, Wang Er i Chen Qingyang. Zatim smo pomoću remove metoda obrisali element Wang Er, a pomoću remove i add metoda izmenili element Chenmo. Na kraju smo pomoću contains metoda proverili da li element Chen Qingyang postoji u set-u i ispisali rezultat.
LinkedHashSet je Set interfejs zasnovan na implementaciji hash tabele; nasleđuje HashSet i koristi povezanu listu za održavanje redosleda umetanja elemenata. Stoga ima i prednosti HashSet-a — brzo pretraživanje, umetanje i brisanje — a istovremeno može održavati i redosled umetanja elemenata.
3)TreeSet
"Erge, ne moraš da objašnjavaš, mogu da pogodim — TreeSet je implementiran pomoću TreeMap (o kom će biti reči kasnije), ali se opet radi o istim operacijama nad ključevima, dok je vrednost popunjena jednim fiksnim Object objektom."
Ovaj, Sanmej je naučila da zaključuje.
Tačno, slično kao TreeMap, TreeSet je uređena kolekcija zasnovana na crveno-crnom drvetu; implementira SortedSet interfejs i može automatski da sortira elemente kolekcije. Sortira se prema prirodnom redosledu ključeva ili prema navedenom komparatoru.
// kreira TreeSet objekat
TreeSet<String> set = new TreeSet<>();
// dodaje elemente
set.add("Chenmo");
set.add("Wang Er");
set.add("Chen Qingyang");
System.out.println(set); // ispisuje [Chenmo, Wang Er, Chen Qingyang]
// briše element
set.remove("Wang Er");
System.out.println(set); // ispisuje [Chenmo, Chen Qingyang]
// menja element: elementi u TreeSet-u ne mogu direktno da se izmene, mora prvo obrisati pa dodati
set.remove("Chen Qingyang");
set.add("Chen Qingyang");
System.out.println(set); // ispisuje [Chenmo, Chen Qingyang]
// traži element
System.out.println(set.contains("Chenmo")); // ispisuje true
System.out.println(set.contains("Wang Er")); // ispisuje falseTreba imati na umu da TreeSet ne dozvoljava umetanje null elementa, jer će inače baciti NullPointerException izuzetak.
"U celini gledano, Set kolekcije nisu glavni fokus, jer je donji sloj svih implementiran pomoću Map-a. Zašto se koristi Map? Sanmej, možeš li da pogodiš razlog?"
"Pusti da razmislim."
"Hm? Zar zato što ključevi Map-a ne dozvoljavaju duplikate i nisu uređeni?"
Bože, Sanmej je opet pogodila.
"Da, napreduješ, Sanmej."
03,Queue
Queue, odnosno red, obično prati princip "prvi ušao, prvi izašao" (FIFO): novi element se umeće na kraj reda, a pri pristupanju elementu vraća se element s početka reda.
1)ArrayDeque
Već iz imena se vidi da je ArrayDeque dvostruki red zasnovan na nizu. Da bi se ispunila potreba za istovremenim umetanjem ili brisanjem elemenata na oba kraja niza, niz mora biti cirkularan, što znači da bilo koja tačka niza može biti posmatrana kao početak ili kraj.
Ovo su dvostruki red koji sadrži 4 elementa i dvostruki red koji sadrži 5 elemenata.

head pokazuje na prvi važeći element s početka reda, a tail pokazuje na prvo slobodno mesto na koje se može umetnuti element s kraja reda. Pošto je niz cirkularan, head ne mora nužno počinjati od 0, niti tail mora uvek biti veći od head.
Hajde da vidimo dodavanje, brisanje, izmenu i pretragu za ArrayDeque.
// kreira ArrayDeque
ArrayDeque<String> deque = new ArrayDeque<>();
// dodaje elemente
deque.add("Chenmo");
deque.add("Wang Er");
deque.add("Chen Qingyang");
// briše element
deque.remove("Wang Er");
// menja element
deque.remove("Chenmo");
deque.add("Snaga ćutanja");
// traži element
boolean hasChenQingYang = deque.contains("Chen Qingyang");
System.out.println("Da li deque sadrži Chen Qingyang? " + hasChenQingYang);2)LinkedList
LinkedList bi se obično svrstao pod List, ali on takođe implementira Deque interfejs i može se koristiti kao red. Drugim rečima, LinkedList istovremeno implementira sve funkcionalnosti Stack-a, Queue-a i PriorityQueue-a.
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{}Drugi rečima, i LinkedList i ArrayDeque su dvostruki redovi (deque) u Java okviru kolekcija; oba podržavaju umetanje i brisanje elemenata na oba kraja reda. Međutim, LinkedList i ArrayDeque se razlikuju u implementaciji:
- Različit donji sloj implementacije: LinkedList je zasnovan na povezanoj listi, dok je ArrayDeque zasnovan na nizu.
- Različita efikasnost slučajnog pristupa: zbog razlike u donjem sloju, LinkedList ima nižu efikasnost slučajnog pristupa, sa vremenskom složenošću O(n), dok ArrayDeque može slučajno pristupati elementima preko indeksa, sa vremenskom složenošću O(1).
- Različita efikasnost iteratora: LinkedList ima nižu efikasnost iteratora, jer mora da prelazi kroz povezanu listu, sa vremenskom složenošću O(n), dok je ArrayDeque-ov iterator efikasniji, jer može direktno pristupati elementima niza, sa vremenskom složenošću O(1).
- Različito zauzeće memorije: pošto je LinkedList zasnovan na povezanoj listi, pri čuvanju elemenata mu je potreban dodatni prostor za čvorove liste, pa mu je zauzeće memorije relativno veće, dok je ArrayDeque zasnovan na nizu, pa mu je zauzeće memorije relativno manje.
Zato pri izboru između LinkedList-a i ArrayDeque-a treba birati prema konkretnom poslovnom scenariju i potrebama. Ako je potrebno često umetanje i brisanje na oba kraja dvostrukog reda i slučajan pristup elementima, razmotrite ArrayDeque; ako je potrebno često umetanje i brisanje na sredini reda, razmotrite LinkedList.
Hajde da vidimo dodavanje, brisanje, izmenu i pretragu kada se LinkedList koristi kao red — obratite pažnju da se znatno razlikuje od kada se koristi kao List.
// kreira LinkedList objekat
LinkedList<String> queue = new LinkedList<>();
// dodaje elemente
queue.offer("Chenmo");
queue.offer("Wang Er");
queue.offer("Chen Qingyang");
System.out.println(queue); // ispisuje [Chenmo, Wang Er, Chen Qingyang]
// briše element
queue.poll();
System.out.println(queue); // ispisuje [Wang Er, Chen Qingyang]
// menja element: elementi LinkedList-a ne mogu direktno da se izmene, mora prvo obrisati pa dodati
String first = queue.poll();
queue.offer("Wang Daer");
System.out.println(queue); // ispisuje [Chen Qingyang, Wang Daer]
// traži element: elementima LinkedList-a može se pristupati pomoću get() metoda
System.out.println(queue.get(0)); // ispisuje Chen Qingyang
System.out.println(queue.contains("Chenmo")); // ispisuje false
// traži element: pomoću iteratora pronalazi Chen Qingyang
// koristi iterator da redom prelazi i pronalazi elemente
Iterator<String> iterator = queue.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
if (element.equals("Chen Qingyang")) {
System.out.println("Pronađeno: " + element);
break;
}
}Kada se LinkedList koristi kao red, može se koristiti offer() metod za dodavanje elementa na kraj reda, a poll() metod za brisanje elementa s početka reda. Dodatno, pošto je LinkedList struktura povezane liste i ne podržava slučajan pristup elementima, ne može se pristupati elementima preko indeksa; potrebno je koristiti iterator ili poll() metod za redovni prelazak kroz elemente.
3)PriorityQueue
PriorityQueue je red prioriteta; redosled napuštanja reda povezan je sa prioritetom elementa — izvršavanjem remove ili poll metoda uvek se vraća element sa najvišim prioritetom.
// kreira PriorityQueue objekat
PriorityQueue<String> queue = new PriorityQueue<>();
// dodaje elemente
queue.offer("Chenmo");
queue.offer("Wang Er");
queue.offer("Chen Qingyang");
System.out.println(queue); // ispisuje [Chenmo, Wang Er, Chen Qingyang]
// briše element
queue.poll();
System.out.println(queue); // ispisuje [Wang Er, Chen Qingyang]
// menja element: PriorityQueue ne podržava direktnu izmenu elemenata, mora prvo obrisati pa dodati
String first = queue.poll();
queue.offer("Zhang San");
System.out.println(queue); // ispisuje [Zhang San, Chen Qingyang]
// traži element: PriorityQueue ne podržava slučajan pristup elementima, može pristupiti samo elementu s početka reda
System.out.println(queue.peek()); // ispisuje Zhang San
System.out.println(queue.contains("Chen Qingyang")); // ispisuje true
// for petljom pronalazi Chen Qingyang
for (String element : queue) {
if (element.equals("Chen Qingyang")) {
System.out.println("Pronađeno: " + element);
break;
}
}Da bi postojao prioritet, elementi moraju implementirati Comparable ili Comparator interfejs (o čemu će biti reči kasnije).
Za početak, hajde da vidimo red prioriteta sortiran po ukupnom rezultatu, implementacijom Comparator interfejsa.
import java.util.Comparator;
import java.util.PriorityQueue;
class Student {
private String name;
private int chineseScore;
private int mathScore;
public Student(String name, int chineseScore, int mathScore) {
this.name = name;
this.chineseScore = chineseScore;
this.mathScore = mathScore;
}
public String getName() {
return name;
}
public int getChineseScore() {
return chineseScore;
}
public int getMathScore() {
return mathScore;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", Ukupan rezultat=" + (chineseScore + mathScore) +
'}';
}
}
class StudentComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
// poredi ukupan rezultat
return Integer.compare(s2.getChineseScore() + s2.getMathScore(),
s1.getChineseScore() + s1.getMathScore());
}
}
public class PriorityQueueComparatorExample {
public static void main(String[] args) {
// kreira red prioriteta sortiran po ukupnom rezultatu
PriorityQueue<Student> queue = new PriorityQueue<>(new StudentComparator());
// dodaje elemente
queue.offer(new Student("Wang Er", 80, 90));
System.out.println(queue);
queue.offer(new Student("Chen Qingyang", 95, 95));
System.out.println(queue);
queue.offer(new Student("Xiao Tuoling", 90, 95));
System.out.println(queue);
queue.offer(new Student("Chenmo", 90, 80));
while (!queue.isEmpty()) {
System.out.print(queue.poll() + " ");
}
}
}Student je objekat učenika, koji sadrži ime, rezultat iz maternjeg jezika i rezultat iz matematike.
StudentComparator implementira Comparator interfejs i sortira po ukupnom rezultatu.
PriorityQueue je red prioriteta, sa parametrom StudentComparator, a zatim smo dodali 4 objekta učenika.
Pogledajmo rezultat:
[Student{name='Wang Er', Ukupan rezultat=170}]
[Student{name='Chen Qingyang', Ukupan rezultat=190}, Student{name='Wang Er', Ukupan rezultat=170}]
[Student{name='Chen Qingyang', Ukupan rezultat=190}, Student{name='Wang Er', Ukupan rezultat=170}, Student{name='Xiao Tuoling', Ukupan rezultat=185}]
Student{name='Chen Qingyang', Ukupan rezultat=190} Student{name='Xiao Tuoling', Ukupan rezultat=185} Student{name='Chenmo', Ukupan rezultat=170} Student{name='Wang Er', Ukupan rezultat=170}Koristili smo offer metod za dodavanje elemenata, a na kraju smo while petljom prelazili kroz elemente (pomoću poll metoda vadili elemente). Iz rezultata se vidi da je PriorityQueue sortirao učenike po ukupnom rezultatu, od najvišeg ka najnižem.
04,Map
Map čuva parove ključ-vrednost; ključevi moraju biti jedinstveni, dok se vrednosti mogu ponavljati.
1)HashMap
HashMap implementira Map interfejs i može brzo da pronađe odgovarajuću vrednost prema ključu — pomoću hash funkcije mapira ključ na poziciju indeksa u hash tabeli, čime se ostvaruje brz pristup. Detaljnije će biti reči kasnije.
Ovde ukratko upoznajmo osobine HashMap-a:
- I ključ i vrednost u HashMap-u mogu biti null. Ako je ključ null, taj ključ se mapira na prvu poziciju hash tabele.
- Kroz parove ključ-vrednost HashMap-a može se proći pomoću iteratora ili forEach metoda.
- HashMap ima početni kapacitet i faktor opterećenja. Početni kapacitet je početna veličina hash tabele, a faktor opterećenja je odnos broja parova ključ-vrednost koje hash tabela može da uskladišti pre proširenja i veličine hash tabele. Podrazumevani početni kapacitet je 16, a faktor opterećenja 0,75.
Hajde da vidimo jednostavno dodavanje, brisanje, izmenu i pretragu.
// kreira HashMap objekat
HashMap<String, String> hashMap = new HashMap<>();
// dodaje parove ključ-vrednost
hashMap.put("Chenmo", "cenzhong");
hashMap.put("Wang Er", "wanger");
hashMap.put("Chen Qingyang", "chenqingyang");
// dohvata vrednost za zadati ključ
String value1 = hashMap.get("Chenmo");
System.out.println("Vrednost za Chenmo je: " + value1);
// menja vrednost za zadati ključ
hashMap.put("Chenmo", "chenmo");
String value2 = hashMap.get("Chenmo");
System.out.println("Nakon izmene, vrednost za Chenmo je: " + value2);
// briše par ključ-vrednost za zadati ključ
hashMap.remove("Wang Er");
// prelazi kroz HashMap
for (String key : hashMap.keySet()) {
String value = hashMap.get(key);
System.out.println("Vrednost za " + key + " je: " + value);
}2)LinkedHashMap
HashMap je već vrlo moćan, ali je neuređen. Ako nam je potreban uređen Map, koristimo LinkedHashMap. LinkedHashMap je podklasa HashMap-a; koristi povezanu listu da bi zabeležio redosled umetanja/pristupanja elementima.
LinkedHashMap se može posmatrati kao spoj HashMap + LinkedList — koristi hash tabelu za čuvanje podataka, a dvostruko povezanu listu za održavanje redosleda.
Hajde da vidimo jednostavan primer.
// kreira LinkedHashMap, umetnuti parovi ključ-vrednost su Chenmo, Wang Er, Chen Qingyang
LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("Chenmo", "cenzhong");
linkedHashMap.put("Wang Er", "wanger");
linkedHashMap.put("Chen Qingyang", "chenqingyang");
// prelazi kroz LinkedHashMap
for (String key : linkedHashMap.keySet()) {
String value = linkedHashMap.get(key);
System.out.println("Vrednost za " + key + " je: " + value);
}Pogledajmo rezultat:
Vrednost za Chenmo je: cenzhong
Vrednost za Wang Er je: wanger
Vrednost za Chen Qingyang je: chenqingyangIz rezultata se vidi da LinkedHashMap održava redosled umetanja parova ključ-vrednost, zar ne? Da bismo uporedili sa LinkedHashMap-om, isprobajmo istim redosledom podataka sa HashMap-om.
// kreira HashMap, umetnuti parovi ključ-vrednost su Chenmo, Wang Er, Chen Qingyang
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("Chenmo", "cenzhong");
hashMap.put("Wang Er", "wanger");
hashMap.put("Chen Qingyang", "chenqingyang");
// prelazi kroz HashMap
for (String key : hashMap.keySet()) {
String value = hashMap.get(key);
System.out.println("Vrednost za " + key + " je: " + value);
}Pogledajmo rezultat:
Vrednost za Chenmo je: cenzhong
Vrednost za Chen Qingyang je: chenqingyang
Vrednost za Wang Er je: wangerHashMap nije održao redosled umetanja parova ključ-vrednost, zar ne?
3)TreeMap
TreeMap implementira SortedMap interfejs, može automatski da sortira ključeve prema prirodnom redosledu ili navedenom komparatoru, i garantuje redosled elemenata. interno koristi crveno-crno drvo za sortiranje i pretragu ključeva.
Još jedan demo sa dodavanjem, brisanjem, izmenom i pretragom:
// kreira TreeMap objekat
Map<String, String> treeMap = new TreeMap<>();
// dodaje parove ključ-vrednost u TreeMap
treeMap.put("Chenmo", "cenzhong");
treeMap.put("Wang Er", "wanger");
treeMap.put("Chen Qingyang", "chenqingyang");
// traži par ključ-vrednost
String name = "Chenmo";
if (treeMap.containsKey(name)) {
System.out.println("Pronađeno " + name + ": " + treeMap.get(name));
} else {
System.out.println("Nije pronađeno " + name);
}
// menja par ključ-vrednost
name = "Wang Er";
if (treeMap.containsKey(name)) {
System.out.println("Pre izmene " + name + ": " + treeMap.get(name));
treeMap.put(name, "newWanger");
System.out.println("Nakon izmene " + name + ": " + treeMap.get(name));
} else {
System.out.println("Nije pronađeno " + name);
}
// briše par ključ-vrednost
name = "Chen Qingyang";
if (treeMap.containsKey(name)) {
System.out.println("Pre brisanja " + name + ": " + treeMap.get(name));
treeMap.remove(name);
System.out.println("Nakon brisanja " + name + ": " + treeMap.get(name));
} else {
System.out.println("Nije pronađeno " + name);
}
// prelazi kroz TreeMap
for (Map.Entry<String, String> entry : treeMap.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}Za razliku od HashMap-a, TreeMap sortira prema redosledu ključeva.
// kreira TreeMap objekat
Map<String, String> treeMap = new TreeMap<>();
// dodaje parove ključ-vrednost u TreeMap
treeMap.put("c", "cat");
treeMap.put("a", "apple");
treeMap.put("b", "banana");
// prelazi kroz TreeMap
for (Map.Entry<String, String> entry : treeMap.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}Pogledajmo rezultat:
a: apple
b: banana
c: catPodrazumevano je već sortirano prema prirodnom redosledu ključeva.
"Dobro, Sanmej, o okviru kolekcija ćemo pričati dovde; kasnije ćemo detaljno obraditi često korišćene kontejnere, kao što su ArrayList, LinkedList, HashMap itd."
"Ovaj, Erge, ovaj članak stvarno pokriva mnogo toga. Iako je sve prilično osnovno, meni kao početniku i dalje treba vremena da svarim." Sanmej nabraši usne.
