Mapa (rečnik) čuva parove ključ → vrednost i omogućava brzo pronalaženje vrednosti po ključu. Skup čuva elemente bez ponavljanja. To su strukture koje se najčešće koriste za brojanje, grupisanje i proveru „da li smo ovo već videli“.
Pre nego što počneš: potrebno predznanje – liste, stringovi. Kako da učiš: svaki primer prekucaj i pokreni, a zadatke na kraju prvo reši sam/a; uputstvo i rešenje otvori tek posle toga. Svi programi su u Javi (Java 17 ili novija); svaki je preveden i pokrenut i daje navedeni izlaz.
HashMap: ključ i vrednost
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
public class Main {
public static void main(String[] args) {
Map<String, Integer> stanovnici = new HashMap<>();
stanovnici.put("Beograd", 1_681_405); // dodavanje para
stanovnici.put("Novi Sad", 368_967);
stanovnici.put("Nis", 249_501);
stanovnici.put("Nis", 249_816); // isti ključ: vrednost se zamenjuje
System.out.println(stanovnici.get("Novi Sad"));
System.out.println(stanovnici.get("Kragujevac")); // nema ključa: null
System.out.println(stanovnici.getOrDefault("Kragujevac", 0));
System.out.println("Ima Nis? " + stanovnici.containsKey("Nis") + ", parova: " + stanovnici.size());
stanovnici.remove("Beograd");
// ispis abecedno po ključu: kopija u TreeMap (HashMap nema određen redosled)
for (Map.Entry<String, Integer> e : new TreeMap<>(stanovnici).entrySet())
System.out.println(e.getKey() + " -> " + e.getValue());
}
}
HashMap ne čuva nikakav određen redosled ključeva. Ako treba sortiran redosled, koristi se TreeMap, a ako treba redosled dodavanja – LinkedHashMap.
Brojanje pojavljivanja
Najčešća upotreba mape: koliko se puta pojavio svaki element. Metoda merge(kljuc, 1, Integer::sum) dodaje 1 na postojeću vrednost ili postavlja 1 za nov ključ.
import java.util.Map;
import java.util.Scanner;
import java.util.TreeMap;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String tekst = sc.nextLine().toLowerCase();
Map<String, Integer> broj = new TreeMap<>(); // ključevi abecedno
for (String rec : tekst.split("[^a-z]+")) {
if (rec.isEmpty()) continue;
broj.merge(rec, 1, Integer::sum); // isto: broj.put(rec, broj.getOrDefault(rec, 0) + 1)
}
System.out.println(broj);
// najčešća reč
String najcesca = null;
for (String r : broj.keySet())
if (najcesca == null || broj.get(r) > broj.get(najcesca))
najcesca = r;
System.out.println("Najcesca: " + najcesca + " (" + broj.get(najcesca) + ")");
}
}
HashSet i TreeSet: skup bez ponavljanja
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
public class Main {
public static void main(String[] args) {
Set<Integer> a = new TreeSet<>(List.of(5, 1, 3, 9, 7, 3, 1)); // duplikati nestaju, sortirano
Set<Integer> b = new TreeSet<>(List.of(3, 4, 5, 6));
System.out.println("a = " + a + ", b = " + b);
Set<Integer> presek = new TreeSet<>(a);
presek.retainAll(b); // zadrži samo zajedničke
Set<Integer> unija = new TreeSet<>(a);
unija.addAll(b);
Set<Integer> razlika = new TreeSet<>(a);
razlika.removeAll(b);
System.out.println("presek " + presek + ", unija " + unija + ", a\\b " + razlika);
// add vraća false ako element već postoji – prvo ponavljanje u nizu
Set<String> videno = new HashSet<>();
for (String s : new String[]{"crvena", "plava", "zuta", "plava", "crvena"})
if (!videno.add(s)) {
System.out.println("Prvo ponavljanje: " + s);
break;
}
}
}
Provera contains je u HashSet-u i HashMap-u praktično trenutna, bez obzira na broj elemenata, dok lista mora da pregleda element po element.
TreeMap: sortirani ključevi i pretraga
import java.util.TreeMap;
public class Main {
public static void main(String[] args) {
// granica bodova -> ocena
TreeMap<Integer, Integer> skala = new TreeMap<>();
skala.put(0, 1);
skala.put(50, 2);
skala.put(65, 3);
skala.put(80, 4);
skala.put(90, 5);
int[] bodovi = {45, 50, 72, 89, 100};
for (int b : bodovi) {
// floorKey: najveći ključ koji je <= b
int ocena = skala.get(skala.floorKey(b));
System.out.println(b + " bodova -> ocena " + ocena);
}
System.out.println("prva granica " + skala.firstKey() + ", poslednja " + skala.lastKey());
}
}
Struktura
Redosled
Kada je koristiti
HashMap / HashSet
nikakav određen
najbrža; kada redosled nije bitan
LinkedHashMap / LinkedHashSet
redosled dodavanja
kada treba zapamtiti redosled
TreeMap / TreeSet
sortiran
sortiran ispis, floorKey, ceilingKey
Mapa sa listom: grupisanje
Vrednost u mapi može biti i lista. Metoda computeIfAbsent pravi praznu listu kada se ključ pojavi prvi put:
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.TreeMap;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Map<String, List<String>> poOdeljenju = new TreeMap<>();
for (int i = 0; i < n; i++) {
String ime = sc.next(), odeljenje = sc.next();
poOdeljenju.computeIfAbsent(odeljenje, k -> new ArrayList<>()).add(ime);
}
for (var e : poOdeljenju.entrySet()) // var: tip zaključuje prevodilac
System.out.println(e.getKey() + ": " + String.join(", ", e.getValue()));
}
}
Zadaci za vežbu
Za svaki zadatak postoji primer, uputstvo i rešenje. Rešenja su provereno tačna na primerima iz teksta.
ZADATAK 01Težina: srednje
Anagrami
Dve reči su anagrami ako imaju ista slova u drugačijem redosledu (pas i sap). Učitava se n, pa n reči od malih slova. Ispisati grupe anagrama (samo grupe sa bar dve reči), svaku u svom redu, reči unutar grupe abecedno, a grupe po prvoj reči abecedno.
Primer
Ulaz
7
sap
list
pas
rak
slit
aps
kar
Izlaz
aps pas sap
kar rak
list slit
Uputstvo
Ključ grupe je reč sa sortiranim slovima (char[] c = rec.toCharArray(); Arrays.sort(c); new String(c)). Grupiši u Map<String, List<String>>, pa sortiraj.
Rešenje (Java)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Map<String, List<String>> grupe = new HashMap<>();
for (int i = 0; i < n; i++) {
String rec = sc.next();
char[] c = rec.toCharArray();
Arrays.sort(c);
grupe.computeIfAbsent(new String(c), k -> new ArrayList<>()).add(rec);
}
List<List<String>> rez = new ArrayList<>();
for (List<String> g : grupe.values())
if (g.size() >= 2) {
Collections.sort(g);
rez.add(g);
}
rez.sort((x, y) -> x.get(0).compareTo(y.get(0)));
for (List<String> g : rez)
System.out.println(String.join(" ", g));
}
}
ZADATAK 02Težina: srednje
Dva broja sa zbirom
Učitavaju se n i k, pa n celih brojeva (n ≤ 200 000). Ispisati broj parova pozicija i < j za koje je a[i] + a[j] = k. Rešenje sa dve petlje je presporo – treba jedan prolaz.
Primer 1
Ulaz
6 7
1 6 3 4 5 2
Izlaz
3
Primer 2
Ulaz
5 4
2 2 2 1 3
Izlaz
4
Uputstvo
Prolazi kroz brojeve redom i u mapi pamti koliko puta se do sada pojavio svaki broj. Za tekući broj x broj parova povećaj za koliko.getOrDefault(k - x, 0), pa tek onda dodaj x u mapu. Rezultat čuvaj u long.
Rešenje (Java)
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
long k = sc.nextLong();
Map<Long, Integer> koliko = new HashMap<>();
long parova = 0;
for (int i = 0; i < n; i++) {
long x = sc.nextLong();
parova += koliko.getOrDefault(k - x, 0); // parovi sa ranijim brojevima
koliko.merge(x, 1, Integer::sum);
}
System.out.println(parova);
}
}
Česte greške i saveti
get za ključ koji ne postoji vraća null; ako vrednost pretvaraš u int, to izaziva NullPointerException. Koristi getOrDefault.
Ne oslanjaj se na redosled ispisa HashMap-e – za sortiran ispis koristi TreeMap.
Ključ u mapi i element skupa ne smeju se menjati dok su u kolekciji (posebno kod sopstvenih klasa).
Za sopstvenu klasu kao ključ moraju postojati metode equals i hashCode; record ih ima automatski.
Proveri znanje
Otvori kviz
Mape i skupovi
1. Šta se dešava kada se put pozove sa ključem koji već postoji?
2. Koja struktura čuva ključeve sortirane?
3. Šta vraća set.add(x) ako x već postoji u skupu?
4. Za šta je mapa najpogodnija?
Podešavanja kolačića
Koristimo kolačiće da bismo vam pružili najbolje moguće iskustvo. Takođe nam omogućavaju da analiziramo ponašanje korisnika kako bismo stalno poboljšavali veb lokaciju za vas.