Bölüm 5: Koleksiyonlar
Giriş
Öğrenme Çıktıları
Koleksiyon çerçevesinin arayüz, uygulama ve algoritma unsurlarını ve arayüz/sınıf hiyerarşisini açıklamak.
List<String> gibi generic türlerle tip güvenli kod yazmak; sarmalayıcı sınıfları ve otomatik kutulamayı kullanmak.
ArrayList, LinkedList, Vector ve Stack'i kullanmak; performans farklarını açıklamak.
Queue, PriorityQueue ve ArrayDeque ile FIFO, öncelik ve LIFO davranışlarını gerçeklemek.
HashSet, TreeSet, HashMap, TreeMap ve bağlantılı sürümlerini doğru yerde seçmek.
Iterator ile güvenle gezinmek; Collections ile sıralamak, karıştırmak, aramak ve düzenlemek.
Koleksiyon Çerçevesi
Neden Koleksiyonlar?
- Koleksiyon (collection): birden çok öğeyi tek bir nesnede saklayan ve yöneten veri yapısıdır.
- Java Koleksiyon Çerçevesi (Java Collections Framework):
java.utilpaketindeki hazır arayüzler, sınıflar ve algoritmalar. - Veri saklamak, sıralamak, aramak ve işlemek için güçlü, test edilmiş, performans ve güvenlik açısından optimize edilmiş araçlar sunar.
- Diziden farkı: boyut dinamiktir;
add,remove,containsgibi hazır metotlar vardır. - Doğru yapıyı seçmek önemlidir: her koleksiyon türü farklı bir ihtiyaca göre tasarlanmıştır.
Dizi: boyut baştan sabit
int[] dizi = new int[3]; // boyut sabit: 3 dizi[0] = 10; dizi[1] = 20; dizi[2] = 30; // dizi[3] = 40; → ArrayIndexOutOfBoundsException
Liste: gerektikçe büyür
List<Integer> liste = new ArrayList<>(); liste.add(10); liste.add(20); liste.add(30); liste.add(40); // sorun yok: büyür System.out.println(liste); System.out.println("boyut: " + liste.size());
[10, 20, 30, 40] boyut: 4
ArrayList yolcu arttıkça büyüyen bir otobüstür.Koleksiyon Çerçevesi
Koleksiyon Türleri
Sıralı, indeksli öğeler; tekrar olabilir. ArrayList, LinkedList
Yalnızca tekil öğeler; aynı öğe ikinci kez eklenmez. HashSet, TreeSet
Anahtar → değer çiftleri; her anahtar bir kez. HashMap, TreeMap
İşlenmeyi bekleyen öğeler; genellikle ilk giren ilk çıkar (FIFO). LinkedList, PriorityQueue
Koleksiyon Çerçevesi
Temel İşlemler ve Tasarım Amaçları
Ekleme, çıkarma, güncelleme ve arama; for-each döngüsüyle kolay gezinme (iterasyon).
Basit ve anlaşılır bir API: kod daha okunur olur, bakımı kolaylaşır.
Veri hacmine ve erişim ihtiyacına göre optimize edilmiş, bellek açısından verimli yapılar.
Generic yapılar (List<String>) yanlış türdeki öğeyi derleme anında yakalar.
Farklı ihtiyaçlar için bir sınıf ailesi; standart kütüphanenin geri kalanıyla uyumlu çalışır.
Sıralama, arama, karıştırma hazırdır; hatalı kullanım istisnayla bildirilir. Zaman kazandırır, güvenilir yazılıma katkı sağlar.
Koleksiyon Çerçevesi
Koleksiyon Arayüzleri
Iterable:for-eachile gezilebilen her şey (iterator()metodu).Collection: tüm koleksiyonların ortak metotları (add,remove,size…).List,Queue,Set:Collection'ı genişleten (extends) alt arayüzler.Map: anahtar-değer yapısı. Çerçevenin parçasıdır amaCollection'dan türemez.
Oklar UML gösterimidir: içi boş üçgen, genişletilen (üst) arayüzü gösterir.
Koleksiyon Çerçevesi
Koleksiyon Sınıfları
LinkedList hem List hem Deque arayüzünü uygular. Mavi kutular arayüz (yalnızca davranış), yeşil kutular new ile nesnesi oluşturulabilen sınıflardır.
Koleksiyon Çerçevesi
Çerçevenin Üç Unsuru
Bir veri yapısının nasıl davranması gerektiğini tanımlar (ne yapılır). Örnek: List sıralı bir listeyi temsil eder.
Arayüzü uygulayan gerçek sınıftır (nasıl yapılır). Örnek: ArrayList, List'i dinamik bir diziyle uygular.
Sıralama, arama gibi işlemleri yapan hazır metotlar. Örnek: Collections.sort() bir listeyi sıralar.
List<String> liste = new ArrayList<>(); // arayüz ← sınıf liste.add("Mavi"); liste.add("Kırmızı"); Collections.sort(liste); // algoritma System.out.println(liste);
[Kırmızı, Mavi]
Koleksiyon Çerçevesi
Arayüze Göre Programlama
- Arayüz bir davranışı tanımlar; sınıflar bu davranışı kendi yöntemleriyle uygular.
- Farklı depolama türleri:
ArrayListdinamik dizi,LinkedListçift yönlü bağlı liste,HashMapanahtar-değer tablosu. - Her sınıf belirli bir veri yapısının gereksinimlerini karşılar ve belirli bir görevi yerine getirir.
- Değişkeni ve parametreyi arayüz türünde tanımlayın: uygulamayı tek satırda değiştirebilirsiniz; kodun geri kalanı ve temel davranış aynı kalır.
public class ListeYazdir { // Parametre türü arayüz: her List ile çalışır static void yazdir(List<String> liste) { for (String s : liste) { System.out.print(s + " "); } System.out.println("(" + liste.size() + " öğe)"); } public static void main(String[] args) { List<String> a = new ArrayList<>(); a.add("Elma"); a.add("Armut"); List<String> b = new LinkedList<>(a); // aynı öğeler b.add("Kiraz"); yazdir(a); yazdir(b); } }
Elma Armut (2 öğe) Elma Armut Kiraz (3 öğe)
Koleksiyon Çerçevesi
Generic Türler ve Tip Güvenliği
List<String> isimler = new ArrayList<>(); isimler.add("Ali"); // isimler.add(42); // derleme hatası String ilk = isimler.get(0); // tür dönüşümü gerekmez List<Integer> notlar = new ArrayList<>(); // List<int> olmaz notlar.add(85); // kutulama: int → Integer int n = notlar.get(0); // kutu açma: Integer → int System.out.println(ilk + " " + n);
Ali 85
<>içine öğe türü yazılır:List<String>“String listesi” demektir.- Yanlış tür derleme anında yakalanır;
getsonucu için tür dönüşümü (cast) gerekmez. - Sağdaki boş
<>: elmas (diamond) işleci, Java 7+; tür soldan çıkarılır.
Koleksiyonlar yalnızca nesne tutar
| İlkel tür | Sarmalayıcı sınıf |
|---|---|
int | Integer |
double | Double |
char | Character |
boolean | Boolean |
long | Long |
İlkel türler için sarmalayıcı (wrapper) sınıf kullanılır. Dönüşüm otomatiktir: otomatik kutulama (autoboxing) ve kutu açma (unboxing).
Koleksiyon Çerçevesi
İlk Örnekler
// İsim listesi (ArrayList) List<String> isimListesi = new ArrayList<>(); isimListesi.add("Ahmet"); isimListesi.add("Ayşe"); System.out.println(isimListesi); // Telefon rehberi (HashMap) Map<String, String> telefonRehberi = new HashMap<>(); telefonRehberi.put("Ahmet", "555-1234"); telefonRehberi.put("Ayşe", "555-9876"); System.out.println(telefonRehberi.get("Ahmet"));
[Ahmet, Ayşe] 555-1234
- İsim listesi:
ArrayListöğeleri eklenme sırasıyla tutar;addsona ekler. - Telefon rehberi:
HashMapbir anahtarı (isim) bir değere (numara) eşler. put(anahtar, değer)ile ekleriz,get(anahtar)ile değeri buluruz.- Listeyi
printlnile yazdırmak öğeleri[ … ]içinde gösterir.
Koleksiyon Çerçevesi
Collection Arayüzü Metotları
| Metot | Görevi | Döndürür |
|---|---|---|
add(E e) | öğeyi koleksiyona ekler | boolean: eklendiyse true |
remove(Object o) | öğeyi koleksiyondan çıkarır | boolean |
size() | eleman sayısını verir | int |
isEmpty() | koleksiyon boş mu? | boolean |
contains(Object o) | öğe koleksiyonda var mı? | boolean |
containsAll(Collection<?> c) | c'nin tüm öğeleri bu koleksiyonda var mı? | boolean |
clear() | tüm öğeleri çıkarır | — |
toArray() | koleksiyonu diziye dönüştürür | Object[] |
iterator() | gezinmek için bir yineleyici verir | Iterator<E> |
forEach(Consumer<? super E> a) | her öğeye bir işlem uygular (Java 8+) | — |
E: öğe türü (generic tür parametresi). ? joker (wildcard): “herhangi bir tür”. Bu metotlar tüm List, Set ve Queue'larda vardır.
Koleksiyon Çerçevesi
Collection Metotları: Örnek
Collection<String> renkler = new ArrayList<>();
renkler.add("kırmızı");
renkler.add("yeşil");
renkler.add("mavi");
System.out.println(renkler.size());
System.out.println(renkler.contains("yeşil"));
renkler.remove("yeşil");
System.out.println(renkler);
Collection<String> aranan = Arrays.asList("mavi", "kırmızı");
System.out.println(renkler.containsAll(aranan));
Object[] dizi = renkler.toArray();
System.out.println(dizi.length);
renkler.clear();
System.out.println(renkler.isEmpty());Çıktı
3 true [kırmızı, mavi] true 2 true
- Değişken türü
Collection: yalnızca ortak metotlar kullanılabilir (indeksligetyok). remove("yeşil")öğeyi değerine göre siler.toArray()kopyalanmış yeni bir dizi döndürür.
Listeler
List Arayüzü
- Öğeler eklenme sırasına göre tutulur: sıralı (ordered) ama sıralanmış (sorted) değil.
- İndeks tabanlı erişim: ilk öğe 0, son öğe
size() − 1. - Aynı öğe birden çok kez bulunabilir.
ArrayList: dinamik dizi, hızlı indeksli erişim.LinkedList: çift yönlü bağlı liste; uçlarda ekleme ve çıkarma hızlı.Vector: eski, senkronize (thread-safe) sürüm; yerineArrayListtercih edilir.
| Metot | Görevi |
|---|---|
add(E e) | sona ekler |
add(int i, E e) | i konumuna ekler |
get(int i) | i'deki öğeyi verir |
set(int i, E e) | i'deki öğeyi değiştirir |
remove(int i) | i'deki öğeyi çıkarır |
remove(Object o) | o'yu çıkarır |
indexOf(Object o) | ilk konumu; yoksa −1 |
size() | eleman sayısı |
Listeler
ArrayList Sınıfı
- Dinamik dizi: öğeleri içerideki bir dizide, eklenme sırasıyla saklar.
AbstractListsınıfından türetilmiştir veListarayüzünü uygular.- Dinamik boyut: iç dizi dolunca kendiliğinden büyür.
get(i)/set(i, e)çok hızlıdır: O(1).- Sona ekleme ortalamada hızlıdır; ortaya ekleme ve ortadan çıkarma öğeleri kaydırdığı için yavaştır: O(n).
ArrayList<String> meyveler = new ArrayList<>(); meyveler.add("Elma"); meyveler.add("Armut"); System.out.println(meyveler.get(1)); // indeksle
Armut
Listeler
ArrayList Nasıl Büyür?
new ArrayList<>(4) ile başlangıç kapasitesi 4 olan bir liste düşünelim: içeride 4 hücrelik bir dizi var, 3'ü dolu.
add("D"): boş hücre var; D doğrudan sona yazılır. Hiçbir öğe taşınmaz: O(1).
add("E"): dizi dolu! Daha büyük yeni bir dizi ayrılır ve eski 4 öğe tek tek kopyalanır: O(n).
E yeni dizinin 4. hücresine yazılır. Eski dizi çöp toplayıcıya (garbage collector) bırakılır.
size() değildir: size() dolu hücre sayısıdır.Listeler · Kodu adım adım çalıştır
ArrayList Metotları: İzleme
Boş bir ArrayList oluşur: size() 0.
add öğeyi sona ekler: Ali 0. indekste.
Dört öğe daha sona eklenir; indeksler 0…4.
Liste yazdırılır: öğeler eklenme sırasıyla.
set(3, "Can"): 3. indeksteki Deniz'in yerine Can yazılır. Boyut değişmez.
remove(4): 4. indeksteki Ece silinir. Son öğe olduğu için kaydırma gerekmez.
add(2, "Fatma"): Cem ve Can birer sağa kayar, Fatma 2. indekse girer.
indexOf("Banu") baştan arar ve ilk konumu döndürür: 1.
contains("Ece"): Ece daha önce silindi, sonuç false.
Son boyut 5: 5 ekleme + 1 araya ekleme − 1 silme.
ArrayList<String> isimler = new ArrayList<>(); isimler.add("Ali"); isimler.add("Banu"); isimler.add("Cem"); isimler.add("Deniz"); isimler.add("Ece"); System.out.println(isimler); isimler.set(3, "Can"); // 3. indeksi değiştir System.out.println(isimler); isimler.remove(4); // 4. indeksi sil System.out.println(isimler); isimler.add(2, "Fatma"); // 2. indekse ekle System.out.println(isimler); int indeks = isimler.indexOf("Banu"); System.out.println("indeks: " + indeks); boolean varMi = isimler.contains("Ece"); System.out.println("Ece var mı: " + varMi); System.out.println("boyut: " + isimler.size());
Listeler
Ortaya Ekleme ve Silme
List<Integer> liste2 = new ArrayList<>(Arrays.asList(10, 20, 30, 40)); liste2.add(1, 15); // araya ekle: 20, 30, 40 sağa kayar System.out.println(liste2); liste2.remove(0); // baştan sil: hepsi sola kayar System.out.println(liste2);
Başlangıç: [10, 20, 30, 40]. Şimdi add(1, 15) çalışacak.
Önce 1. indeksten sonraki öğeler (sondan başlayarak) birer sağa kayar; 1. hücre boşalır.
15 boşalan hücreye yazılır. n öğeli listede en kötü durumda n kaydırma: O(n).
remove(0): 10 silinir, arkasındaki 4 öğe birer sola kayar.
Sonuç. Sondan silmede kaydırma gerekmez: O(1). Baştan/ortadan silmede O(n).
[10, 15, 20, 30, 40] [15, 20, 30, 40]
Listeler
LinkedList Sınıfı
- Çift yönlü bağlı liste: öğeler düğümlerde (node) saklanır; her düğüm değeri ve önceki (prev) ile sonraki (next) düğümün referansını tutar.
AbstractSequentialListsınıfından türetilmiştir;ListveDequearayüzlerini uygular.- Esnek boyut: kapasite yoktur; her ekleme yeni bir düğüm oluşturur, kaydırma yapılmaz.
- Uçlarda ekleme ve çıkarma O(1); ancak
get(i)düğümleri tek tek yürür: O(n).
Benzetme: el ele tutuşmuş bir sıra insan. Araya biri girecekse yalnızca iki kişi el değiştirir; ama 3. kişiyi bulmak için baştan saymak gerekir.
Listeler
LinkedList Örneği
LinkedList<String> meyveler = new LinkedList<>(); meyveler.add("Elma"); meyveler.add("Armut"); meyveler.addFirst("Kiraz"); // başa ekle meyveler.addLast("Muz"); // sona ekle System.out.println(meyveler); System.out.println(meyveler.getFirst()); System.out.println(meyveler.getLast()); meyveler.removeFirst(); System.out.println(meyveler);
[Kiraz, Elma, Armut, Muz] Kiraz Muz [Elma, Armut, Muz]
| Metot | Görevi |
|---|---|
addFirst(e) | başa ekler |
addLast(e) | sona ekler |
getFirst() | ilk öğeyi verir |
getLast() | son öğeyi verir |
removeFirst() | ilk öğeyi çıkarıp verir |
removeLast() | son öğeyi çıkarıp verir |
Bu metotlar Deque arayüzünden gelir; add, get, remove(i) ise List'ten.
Listeler
ArrayList mi, LinkedList mi?
| İşlem | ArrayList | LinkedList |
|---|---|---|
get(i), set(i, e) | O(1) | O(n): düğüm düğüm yürür |
Sona ekleme add(e) | O(1) ortalama (arada bir kopyalama) | O(1) |
| Başa ekleme / baştan silme | O(n): tüm öğeler kayar | O(1) |
| Ortaya ekleme / ortadan silme | O(n): kaydırma | O(n): konumu bulma + O(1) bağlama |
| Bellek kullanımı | az: yalnızca dizi | fazla: her düğümde 2 ek referans |
LinkedList (ya da kuyruk/yığın için ArrayDeque) tercih edilebilir.Listeler
Vector Sınıfı
Listarayüzünü uygulayan, genişletilebilir bir dinamik dizidir.- Belirtilen (varsayılan 10) kapasiteyle başlar; doldukça kapasitesi iki katına çıkar.
- Metotları senkronizedir (synchronized): çoklu iş parçacıklı ortamda güvenle kullanılabilir; ama bu her çağrıda ek maliyettir.
- Java 1.0'dan kalmadır; modern kodda daha hafif ve hızlı
ArrayListtercih edilir.
Vector<Integer> v = new Vector<>(); // kapasite: 10 for (int i = 1; i <= 11; i++) { v.addElement(i * 10); } System.out.println(v.size() + " / " + v.capacity()); System.out.println(v.elementAt(0)); v.removeElement(110); // değeri 110 olan öğe System.out.println(v.size() + " / " + v.capacity());
11 / 20 10 10 / 20
11. eleman eklenince kapasite 10 → 20 olur. Silme kapasiteyi küçültmez.
addElement(E obj) | elementAt(int i) | removeElement(Object obj) | size() | capacity() |
|---|---|---|---|---|
| eleman ekler | i'deki elemanı verir | elemanı çıkarır | eleman sayısı | mevcut kapasite |
Listeler
Stack Sınıfı
- LIFO (Last In, First Out): son giren ilk çıkar.
- En son eklenen en üstte (top), en eski eklenen en altta (base) durur.
Vectorsınıfından türetilmiştir (genişletilmiş bir sürümüdür).- Kullanım: geri alma (undo), metin ve ifade analizi (parantez denetimi), derinlik öncelikli arama, metot çağrı yığını.
- Modern kodda yerine
Dequearayüzünü uygulayanArrayDeque(veyaLinkedList) önerilir.
Benzetme: üst üste konmuş tabaklar; tabak hep en üstten alınır ve en üste konur.
| Metot | Görevi |
|---|---|
push(E item) | en üste ekler |
pop() | en üsttekini çıkarır ve döndürür |
peek() | en üsttekini döndürür, çıkarmaz |
empty() | yığın boş mu? |
search(Object o) | üstten 1'den başlayan konum; yoksa −1 |
Listeler · Kodu adım adım çalıştır
Stack: İzleme
Boş bir yığın oluşur.
push("A"): A en üste konur.
push("B"): B, A'nın üstüne.
push("C"): en üstte artık C var.
println öğeleri alttan üste yazar: [A, B, C].
peek() en üsttekini (C) döndürür ama çıkarmaz.
pop() C'yi çıkarır ve döndürür: son giren ilk çıktı.
search("A") konumu üstten 1'den sayar: B 1, A 2.
empty(): yığında 2 öğe var, sonuç false.
Stack<String> yigin = new Stack<>();
yigin.push("A");
yigin.push("B");
yigin.push("C");
System.out.println(yigin);
System.out.println(yigin.peek());
System.out.println(yigin.pop());
System.out.println(yigin.search("A"));
System.out.println(yigin.empty());Listeler
Listede Gezinme
List<String> dersler = new ArrayList<>( Arrays.asList("Fizik", "Java", "Devre")); // 1) İndeksli for for (int i = 0; i < dersler.size(); i++) { System.out.print(dersler.get(i) + " "); } System.out.println(); // 2) Gelişmiş for (for-each) for (String d : dersler) { System.out.print(d + " "); } System.out.println(); // 3) forEach + lambda (Java 8+) dersler.forEach(d -> System.out.print(d + " ")); System.out.println();
Çıktı
Fizik Java Devre Fizik Java Devre Fizik Java Devre
- İndeksli for: indekse ihtiyaç olduğunda (yalnızca listelerde).
- for-each: en okunur yol; tüm koleksiyonlarda çalışır.
- forEach + lambda: Java 8+ kısa yazım.
- Gezinirken öğe silmek gerekiyorsa
Iteratorkullanılır (ileride).
Kuyruklar
Queue Arayüzü
- FIFO (First-In-First-Out): ilk giren ilk çıkar.
- Öğeler kuyruğa eklendikleri sırayla çıkarılır; yeni öğe sona girer, işlenecek öğe baştan alınır.
- Öğeler genellikle
offer,pollvepeekmetotlarıyla işlenir. - Uygulamalar:
LinkedList(çift yönlü bağlı liste),PriorityQueue(önceliğe göre; FIFO değil),ArrayDeque(dinamik dizi). - Kullanım: yazıcı kuyruğu, görev sırası, genişlik öncelikli arama.
Benzetme: market kasası. Sıraya en sondan girilir, ödemeyi en öndeki yapar.
| İşlem | Hata fırlatır | Özel değer döner |
|---|---|---|
| Ekle (sona) | add(e) | offer(e) → false |
| Çıkar (baştan) | remove() | poll() → null |
| Bak (baştakine) | element() | peek() → null |
Kuyruk boşken remove() ve element() NoSuchElementException fırlatır; poll() ve peek() ise null döndürür. size(): eleman sayısı.
Kuyruklar · Kodu adım adım çalıştır
Queue: İzleme
Kuyruk Queue türünde, nesne LinkedList.
offer("Ali"): Ali kuyruğa girer; hem baş hem son o.
Banu sona girer.
Cem sona girer.
Kuyruk baştan sona yazdırılır.
peek() baştakini döndürür, çıkarmaz.
poll() baştakini çıkarır ve döndürür: ilk giren Ali ilk çıktı.
Sıradaki Banu çıkar.
size(): kuyrukta 1 öğe kaldı.
Cem de çıkar; kuyruk boşaldı.
Boş kuyrukta poll() hata vermez, null döndürür.
Queue<String> kuyruk = new LinkedList<>();
kuyruk.offer("Ali");
kuyruk.offer("Banu");
kuyruk.offer("Cem");
System.out.println(kuyruk);
System.out.println(kuyruk.peek());
System.out.println(kuyruk.poll());
System.out.println(kuyruk.poll());
System.out.println(kuyruk.size());
System.out.println(kuyruk.poll());
System.out.println(kuyruk.poll());Kuyruklar
PriorityQueue Sınıfı
- Öncelikli kuyruk (priority queue): çıkan öğe her zaman en öncelikli olandır, eklenme sırası değil.
- Varsayılan öncelik doğal sıradır: en küçük öğe önce çıkar. Tersi için karşılaştırıcı verilir.
- Öğeler karşılaştırılabilir (
Comparable) olmalı ya da bir karşılaştırıcı (Comparator) verilmelidir. - İçte ikili yığın (binary heap) kullanır:
add/pollO(log n),peekO(1); dinamik olarak büyür. - Kullanım: görev zamanlama, acil servis sırası, en kısa yol algoritmaları.
| Metot | Görevi |
|---|---|
add(E e) | eleman ekler |
poll() | en öncelikliyi çıkarır ve döndürür |
peek() | en öncelikliyi döndürür, çıkarmaz |
remove(Object o) | belirtilen elemanı çıkarır |
size() | eleman sayısı |
Kuyruklar
PriorityQueue Örneği
PriorityQueue<Integer> pq = new PriorityQueue<>(); pq.add(30); pq.add(10); pq.add(40); pq.add(20); System.out.println(pq.peek()); // en küçük System.out.println(pq); // iç düzen (yığın) while (!pq.isEmpty()) { System.out.print(pq.poll() + " "); } System.out.println();
10 [10, 20, 40, 30] 10 20 30 40
println(pq) sıralı değildir: iç dizi yalnızca “her ebeveyn çocuklarından küçük” kuralına uyar. Sıralı sonuç için poll ile tek tek çıkarılır.
Kuyruklar
Önceliği Belirlemek
class Gorev implements Comparable<Gorev> { String ad; int oncelik; // küçük = acil Gorev(String ad, int oncelik) { this.ad = ad; this.oncelik = oncelik; } @Override public int compareTo(Gorev diger) { return Integer.compare(oncelik, diger.oncelik); } @Override public String toString() { return ad + "(" + oncelik + ")"; } }
compareTo negatif dönerse this önce gelir. Collections.reverseOrder() doğal sırayı tersine çevirir: en büyük önce çıkar.
PriorityQueue<Gorev> gorevler =
new PriorityQueue<>();
gorevler.add(new Gorev("Rapor", 3));
gorevler.add(new Gorev("Arıza", 1));
gorevler.add(new Gorev("Toplantı", 2));
while (!gorevler.isEmpty()) {
System.out.println(gorevler.poll());
}Arıza(1) Toplantı(2) Rapor(3)
PriorityQueue<Integer> buyukOnce =
new PriorityQueue<>(
Collections.reverseOrder());
buyukOnce.add(30);
buyukOnce.add(10);
buyukOnce.add(40);
System.out.println(buyukOnce.poll());40
Kuyruklar
Deque Arayüzü
- Deque (Double-Ended Queue, “dek” okunur): hem baştan hem sondan eleman eklenebilen ve çıkarılabilen çift uçlu kuyruk.
Queue(FIFO) veStack(LIFO) işlevselliğini birleştirir.- Uygulamalar:
LinkedList(çift yönlü bağlı liste) veArrayDeque(dinamik dizi).
| Baş | Görevi | Son | Görevi |
|---|---|---|---|
addFirst(e) | başa ekler | addLast(e) | sona ekler |
removeFirst() | baştakini çıkarır, döndürür | removeLast() | sondakini çıkarır, döndürür |
getFirst() | baştakini döndürür | getLast() | sondakini döndürür |
remove…/get… boş deque'de istisna fırlatır; poll…/peek… null döndürür. size(): eleman sayısı.
Kuyruklar
ArrayDeque Sınıfı
- Çift uçlu kuyruk yapısını dinamik (dairesel) bir diziyle uygular.
- Hem kuyruk hem yığın işlemlerini destekler.
- Genellikle
LinkedList'ten veStack'ten daha hızlı ve hafiftir; yığın ve kuyruk için önerilen sınıftır. nullöğe kabul etmez.
| Metot | Görevi |
|---|---|
pollFirst() / pollLast() | baştakini / sondakini çıkarır, döndürür |
peekFirst() / peekLast() | baştakini / sondakini döndürür, çıkarmaz |
Yığın olarak (Stack yerine)
Deque<String> yigin = new ArrayDeque<>(); yigin.push("A"); // başa ekler yigin.push("B"); System.out.println(yigin.pop());
B
push/pop/peek baş uçta çalışır. Kuyruk olarak: offer sona ekler, poll baştan alır.
Kuyruklar · Kodu adım adım çalıştır
ArrayDeque: İzleme
Boş bir ArrayDeque.
addFirst(5): 5 başa eklenir (tek öğe).
addLast(10): 10 sona eklenir.
addFirst(1): 1 başa eklenir, 5 ve 10 yerinde kalır.
Baştan sona yazdırılır.
pollFirst() baştaki 1'i çıkarır; otomatik kutu açma ile int'e atanır.
pollLast() sondaki 10'u çıkarır.
İki değer yazdırılır.
peekFirst() baştaki 5'i döndürür, çıkarmaz.
ArrayDeque<Integer> sayilar = new ArrayDeque<>(); sayilar.addFirst(5); sayilar.addLast(10); sayilar.addFirst(1); System.out.println(sayilar); int ilkSayi = sayilar.pollFirst(); int sonSayi = sayilar.pollLast(); System.out.println(ilkSayi + " " + sonSayi); System.out.println(sayilar.peekFirst());
Kümeler
Set Arayüzü
- Tekil öğeleri saklar; matematikteki küme gibidir ve küme işlemlerine uygundur.
- Her öğeden yalnızca bir tane bulunur: var olan öğeyi
addeklemez,falsedöndürür. - Genel olarak sıra garantisi vermez (sıra, uygulamaya bağlıdır).
- Ekleme, çıkarma ve arama hızlıdır.
HashSet: sırasız.LinkedHashSet: eklenme sırası.TreeSet: sıralı (doğal sıra ya daComparator).
| Metot | Görevi |
|---|---|
add(E e) | öğeyi kümeye ekler |
remove(Object o) | öğeyi kümeden çıkarır |
contains(Object o) | öğe kümede var mı? |
size() | eleman sayısı |
Set<String> meyveler = new HashSet<>();
System.out.println(meyveler.add("Elma"));
System.out.println(meyveler.add("Armut"));
System.out.println(meyveler.add("Elma"));
System.out.println(meyveler.size());
System.out.println(meyveler.contains("Armut"));
meyveler.remove("Armut");
System.out.println(meyveler);true true false 2 true [Elma]
Kümeler
HashSet ve Karma (Hashing)
- Tekil elemanları sırasız saklar;
AbstractSet'ten türetilmiştir veSet'i uygular. - Öğenin
hashCode()değerinden bir kova (bucket) numarası hesaplanır; öğe doğrudan o kovaya gider: ekleme ve arama ortalama O(1). - Depolama sırası garanti edilmez: gezinme kovaların sırasıyla yapılır.
İçte 16 kovalı bir tablo vardır (dolulukla birlikte büyür).
add("muz"): karma değerinden kova 3 hesaplanır, muz oraya yerleşir.
add("elma"): kova 4.
add("kiraz"): kova 8.
İkinci add("elma"): kova 4'te equals ile eşit bir öğe var. Eklenmez; add false döner.
add("armut"): kova 7. Gezinme sırası kovalara göre: [muz, elma, armut, kiraz].
Kümeler
LinkedHashSet Sınıfı
- Sadece tekil elemanları içeren bir küme;
HashSet'ten türer. - Ek olarak elemanları bir bağlı listeyle birbirine bağlar: eklenme sırası korunur.
- Hızlı erişim sağlar ve elemanların benzersizliğini garanti eder.
- Hem performans hem sıra önemliyse tercih edilir; sıra önemli değilse ve performans kritikse
HashSetkullanılır.
LinkedHashSet<Integer> sayilar =
new LinkedHashSet<>();
sayilar.add(5);
sayilar.add(10);
sayilar.add(5); // tekrar: eklenmez
sayilar.add(1);
System.out.println(sayilar);[5, 10, 1]
| Metot | Görevi |
|---|---|
add(E e) | eleman ekler |
remove(Object o) | elemanı çıkarır |
contains(Object o) | eleman var mı? |
size() | eleman sayısı |
clear() | tüm elemanları çıkarır |
Kümeler
Üç Kümenin Sırası
String[] kelimeler = {"muz", "elma", "kiraz", "elma", "armut"};
Set<String> h = new HashSet<>();
Set<String> l = new LinkedHashSet<>();
Set<String> t = new TreeSet<>();
for (String k : kelimeler) {
h.add(k);
l.add(k);
t.add(k);
}
System.out.println("HashSet: " + h);
System.out.println("LinkedHashSet: " + l);
System.out.println("TreeSet: " + t);HashSet: [muz, elma, armut, kiraz] LinkedHashSet: [muz, elma, kiraz, armut] TreeSet: [armut, elma, kiraz, muz]
| Sınıf | Gezinme sırası | Temel yapı | add / contains |
|---|---|---|---|
HashSet | garanti yok (kova sırası) | karma tablosu | O(1) ortalama |
LinkedHashSet | eklenme sırası | karma tablosu + bağlı liste | O(1) ortalama |
TreeSet | sıralı (küçükten büyüğe) | kırmızı-siyah ağaç | O(log n) |
Kümeler
Kendi Sınıflarımız ve HashSet
class Nokta { int x, y; Nokta(int x, int y) { this.x = x; this.y = y; } @Override public boolean equals(Object o) { if (!(o instanceof Nokta)) return false; Nokta n = (Nokta) o; return x == n.x && y == n.y; } @Override public int hashCode() { return Objects.hash(x, y); } }
NoktaA: aynı sınıf, equals/hashCode yok
Set<NoktaA> s1 = new HashSet<>(); s1.add(new NoktaA(1, 2)); s1.add(new NoktaA(1, 2)); System.out.println(s1.size()); Set<Nokta> s2 = new HashSet<>(); s2.add(new Nokta(1, 2)); s2.add(new Nokta(1, 2)); System.out.println(s2.size());
2 1
NoktaA: iki nesne farklı sayılır (Object'inequals'ı referansları karşılaştırır) → boyut 2.Nokta:equalsvehashCodegeçersiz kılındı → aynı nokta bir kez → boyut 1.
Kural: eşit nesnelerin hashCode değeri de eşit olmalı: kova hashCode ile bulunur, sonra equals ile karşılaştırılır.
Kümeler
SortedSet ve TreeSet
SortedSet: elemanları sıralı saklayan tekil küme arayüzü.- Sıralama doğal sıraya (
Comparable) ya da verilen birComparator'a göre yapılır. - Alt küme ve üst küme işlemleri sunar.
TreeSet:AbstractSet'ten türetilir,NavigableSet(dolayısıylaSortedSet) arayüzünü uygular.- İçte kırmızı-siyah ağaç: ekleme, silme, arama O(log n).
| Metot | Görevi |
|---|---|
first() / last() | en küçük / en büyük eleman |
headSet(to) | to'dan küçükler (to hariç) |
tailSet(from) | from ve büyükler (from dahil) |
subSet(from, to) | from dahil, to hariç |
comparator() | sıralayan Comparator; doğal sırada null |
add, remove | ekleme, çıkarma |
Kümeler
TreeSet Örneği
TreeSet<Integer> notlar = new TreeSet<>(); notlar.add(70); notlar.add(50); notlar.add(90); notlar.add(60); notlar.add(80); System.out.println(notlar); System.out.println(notlar.first() + " " + notlar.last()); System.out.println(notlar.headSet(70)); // 70 hariç System.out.println(notlar.tailSet(70)); // 70 dahil System.out.println(notlar.subSet(60, 90)); // [60, 90) System.out.println(notlar.comparator()); // doğal sıra
TreeSet<String> meyveler = new TreeSet<>();
meyveler.add("Elma");
meyveler.add("Armut");
System.out.println(meyveler);Çıktı
[50, 60, 70, 80, 90] 50 90 [50, 60] [70, 80, 90] [60, 70, 80] null [Armut, Elma]
Öğeler hangi sırayla eklenirse eklensin sıralı tutulur. Dizgiler alfabetik (karakter kodu) sırayla dizilir.
Kümeler
Küme İşlemleri
Set<Integer> a = new TreeSet<>(Arrays.asList(1, 2, 3, 4)); Set<Integer> b = new TreeSet<>(Arrays.asList(3, 4, 5)); Set<Integer> birlesim = new TreeSet<>(a); birlesim.addAll(b); Set<Integer> kesisim = new TreeSet<>(a); kesisim.retainAll(b); Set<Integer> fark = new TreeSet<>(a); fark.removeAll(b); System.out.println("A ∪ B = " + birlesim); System.out.println("A ∩ B = " + kesisim); System.out.println("A − B = " + fark); System.out.println(a.containsAll(kesisim));
A ∪ B = [1, 2, 3, 4, 5] A ∩ B = [3, 4] A − B = [1, 2] true
| İşlem | Metot |
|---|---|
| birleşim ∪ | addAll |
| kesişim ∩ | retainAll |
| fark − | removeAll |
| alt küme ⊆ | containsAll |
Bu metotlar çağrıldığı kümeyi değiştirir; bu yüzden önce kopya alınır.
Eşlemeler
Map Arayüzü
- Anahtar-değer (key-value) çiftlerini saklar: her anahtar bir değere eşlenir.
- Anahtarlar tekildir; değerler tekrar edebilir.
- Anahtar üzerinden hızlı erişim sağlar; çiftler üzerinde işlem yapmaya olanak tanır.
HashMap: sıra garantisi yok.LinkedHashMap: eklenme sırası.TreeMap: anahtarlar sıralı (doğal sıra ya daComparator).
Benzetme: sözlük. Kelime (anahtar) ile anlamını (değer) bulursunuz; aynı kelime iki kez yer almaz.
Eşlemeler
Map Metotları
| Metot | Görevi |
|---|---|
put(K key, V value) | anahtarı değerle eşler; anahtar varsa değeri değiştirir ve eskisini döndürür |
get(Object key) | anahtarın değerini döndürür; anahtar yoksa null |
remove(Object key) | anahtarı ve değerini çıkarır |
containsKey(Object key) | anahtar eşlemede var mı? |
containsValue(Object v) | değer eşlemede var mı? |
keySet() | tüm anahtarları bir Set olarak döndürür |
values() | tüm değerleri bir Collection olarak döndürür |
entrySet() | tüm anahtar-değer çiftlerini bir Set<Map.Entry<K, V>> olarak döndürür |
size(), isEmpty() | çift sayısı, boş mu? |
getOrDefault(key, v) | anahtar yoksa v'yi döndürür (Java 8+) |
K: anahtar türü, V: değer türü. Örnek: Map<String, Integer> isimden nota eşleme.
Eşlemeler
HashMap Sınıfı
HashMap<String, Double> urunFiyatlari = new HashMap<>();
urunFiyatlari.put("Telefon", 2000.0);
urunFiyatlari.put("Kulaklık", 350.0);
urunFiyatlari.put("Kılıf", 120.0);
Double eski = urunFiyatlari.put("Telefon", 1800.0);
System.out.println(eski);
System.out.println(urunFiyatlari.get("Telefon"));
System.out.println(urunFiyatlari.get("Tablet"));
System.out.println(urunFiyatlari.containsKey("Kılıf"));
urunFiyatlari.remove("Kılıf");
System.out.println(urunFiyatlari.size());2000.0 1800.0 null true 2
urunFiyatlari.put(null, 0.0); // tek null anahtar urunFiyatlari.put("Kalem", null); // null değer System.out.println(urunFiyatlari.size());
4
- Anahtar-değer çiftlerini karma tablosunda saklar:
get/putortalama O(1). AbstractMap'ten türetilmiştir veMap'i uygular.- Tekil anahtarlar: aynı anahtarla
putdeğeri değiştirir. - Null: bir
nullanahtara ve birden çoknulldeğere izin verir. - Elemanlar sırasız depolanır.
Eşlemeler
Map Üzerinde Gezinme
Map<String, Integer> notlar = new TreeMap<>(); notlar.put("Cem", 72); notlar.put("Ayşe", 95); notlar.put("Banu", 60); for (String isim : notlar.keySet()) { System.out.print(isim + " "); } System.out.println(); for (Integer not : notlar.values()) { System.out.print(not + " "); } System.out.println(); for (Map.Entry<String, Integer> g : notlar.entrySet()) { System.out.println(g.getKey() + " → " + g.getValue()); }
Ayşe Banu Cem 95 60 72 Ayşe → 95 Banu → 60 Cem → 72
keySet(): yalnız anahtarlar.values(): yalnız değerler.entrySet(): her çift birMap.Entry;getKey()vegetValue()ile okunur. Hem anahtar hem değer gerekiyorsa en verimli yol budur.Mapdoğrudanfor-each'e verilemez:Iterabledeğildir.
Eşlemeler · Kodu adım adım çalıştır
Kelime Sayma: İzleme
Metin ve boş bir TreeMap hazırlanır. split(" ") metni kelimelere böler.
"elma" ilk kez görüldü: put(k, 1).
"armut" ilk kez görüldü: put(k, 1).
"elma" zaten var: eski değer 1 alınır, 2 yazılır.
"kiraz" ilk kez görüldü: put(k, 1).
"armut" zaten var: eski değer 1 alınır, 2 yazılır.
"elma" zaten var: eski değer 2 alınır, 3 yazılır.
Döngü bitti. TreeMap anahtarları alfabetik sırayla yazdırır.
String metin = "elma armut elma kiraz armut elma"; Map<String, Integer> sayac = new TreeMap<>(); for (String k : metin.split(" ")) { if (sayac.containsKey(k)) { sayac.put(k, sayac.get(k) + 1); } else { sayac.put(k, 1); } } System.out.println(sayac);
Eşlemeler
LinkedHashMap Sınıfı
- Tekil anahtar-değer çiftlerini içeren bir eşleme;
HashMap'ten türer. - Her eleman bir anahtar (key) ve bir değer (value) çiftidir; anahtarlar tekildir.
- Çiftleri bağlı listeyle birbirine bağlar: eklenme sırası korunur.
- Performans ve sıra birlikte önemliyse tercih edilir; sıra önemli değilse
HashMapyeterlidir.
Map<String, String> rehber = new LinkedHashMap<>(); rehber.put("Zeynep", "555-1111"); rehber.put("Ahmet", "555-1234"); rehber.put("Mert", "555-2222"); Map<String, String> h = new HashMap<>(rehber); Map<String, String> t = new TreeMap<>(rehber); System.out.println("LinkedHashMap: " + rehber); System.out.println("HashMap: " + h); System.out.println("TreeMap: " + t);
LinkedHashMap: {Zeynep=555-1111, Ahmet=555-1234, Mert=555-2222}
HashMap: {Ahmet=555-1234, Mert=555-2222, Zeynep=555-1111}
TreeMap: {Ahmet=555-1234, Mert=555-2222, Zeynep=555-1111}Temel metotlar Map ile aynıdır: put, remove, get, containsKey, size.
Eşlemeler
Hashtable Sınıfı
- Anahtar-değer çiftlerini saklayan, senkronize (thread-safe) eski bir eşleme sınıfıdır (Java 1.0).
HashMap'ten farkı:HashMapsenkronize değildir;Hashtable'ın her metodu kilitlidir.- Anahtarlar da değerler de
nullolamaz. - Kilitleme yüzünden modern alternatiflerden yavaştır; tek iş parçacığında
HashMap, çok iş parçacığındaConcurrentHashMaptercih edilir. - Metotlar:
put,remove,get,containsKey,size.
Hashtable<String, String> telefonRehberi = new Hashtable<>(); telefonRehberi.put("Ahmet", "555-1234"); System.out.println(telefonRehberi.get("Ahmet")); System.out.println(telefonRehberi.containsKey("Ayşe")); // telefonRehberi.put(null, "x"); → NullPointerException
555-1234 false
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Object.hashCode()" because "key" is null
Eşlemeler
SortedMap ve TreeMap
SortedMap: anahtarları sıralı saklayan eşleme arayüzü; her anahtar bir kez bulunur.- Alt harita ve üst harita gibi işlemler sunar.
TreeMap:AbstractMap'ten türetilir,NavigableMaparayüzünü uygular.- Anahtarlar doğal sıraya ya da verilen
Comparator'a göre dizilir. - İçte kırmızı-siyah ağaç (red-black tree):
get/putO(log n).
| Metot | Görevi |
|---|---|
firstKey() / lastKey() | en küçük / en büyük anahtar |
headMap(to) | to'dan küçük anahtarlar (hariç) |
tailMap(from) | from ve büyükleri (dahil) |
subMap(from, to) | from dahil, to hariç |
comparator() | sıralayan Comparator (doğal sırada null) |
put, get, remove | Map ile aynı |
Eşlemeler
TreeMap Örneği
TreeMap<String, Double> urunFiyatlari = new TreeMap<>();
urunFiyatlari.put("Telefon", 2000.0);
urunFiyatlari.put("Kalem", 15.0);
urunFiyatlari.put("Defter", 40.0);
urunFiyatlari.put("Silgi", 5.0);
System.out.println(urunFiyatlari);
System.out.println(urunFiyatlari.firstKey());
System.out.println(urunFiyatlari.lastKey());
System.out.println(urunFiyatlari.headMap("Kalem"));
System.out.println(urunFiyatlari.tailMap("Kalem"));
System.out.println(urunFiyatlari.subMap("Defter", "Silgi"));Çıktı
{Defter=40.0, Kalem=15.0, Silgi=5.0, Telefon=2000.0}
Defter
Telefon
{Defter=40.0}
{Kalem=15.0, Silgi=5.0, Telefon=2000.0}
{Defter=40.0, Kalem=15.0}Eşlemeler
Map Sınıflarını Karşılaştırma
| HashMap | LinkedHashMap | TreeMap | Hashtable | |
|---|---|---|---|---|
| Gezinme sırası | garanti yok | eklenme sırası | anahtar sıralı | garanti yok |
get / put | O(1) ortalama | O(1) ortalama | O(log n) | O(1) ortalama, kilitli |
null anahtar | bir tane | bir tane | hayır | hayır |
null değer | evet | evet | evet | hayır |
| Senkronize | hayır | hayır | hayır | evet (eski) |
| Ne zaman? | varsayılan seçim | sıra korunmalı | sıralı anahtar, aralık sorgusu | eski kod |
HashSet, LinkedHashSet ve TreeSet içte sırasıyla HashMap, LinkedHashMap ve TreeMap kullanır.Yineleyici
Iterator
- Yineleyici (iterator): koleksiyonda öğeleri sırayla gezmek için kullanılan nesne.
- Koleksiyonun iç yapısını bilmeden (dizi, ağaç, karma tablosu…) her öğeye erişmeyi sağlar.
- Gezerken güvenli silme yapılabilen tek yoldur.
for-eachdöngüsü arka planda birIteratorkullanır.- Listeler için
ListIteratorayrıca geriye gitmeyi,addvesetişlemlerini destekler.
| Metot | Görevi |
|---|---|
hasNext() | bir sonraki öğe var mı? |
next() | sonraki öğeyi döndürür, imleci ilerletir |
remove() | son next() ile alınan öğeyi koleksiyondan çıkarır |
Genellikle while (it.hasNext()) döngüsüyle (veya for ile) kullanılır.
Yineleyici · Kodu adım adım çalıştır
Iterator: İzleme
Liste hazırlanır: [3, 8, 5].
iterator(): imleç ilk öğenin önüne konur.
hasNext() true; next() 3'ü döndürür ve imleci ilerletir.
Öğe yazdırılır.
hasNext() true; next() 8'i döndürür ve imleci ilerletir.
Öğe yazdırılır.
hasNext() true; next() 5'i döndürür ve imleci ilerletir.
Öğe yazdırılır.
İmleç sonda: hasNext() false, döngü biter.
ArrayList<Integer> liste = new ArrayList<>(); liste.add(3); liste.add(8); liste.add(5); Iterator<Integer> iterator = liste.iterator(); while (iterator.hasNext()) { Integer sayi = iterator.next(); // Eleman üzerinde işlemleri gerçekleştir. System.out.println(sayi); }
Yineleyici
Gezinirken Silme
Yanlış: for-each içinde koleksiyondan silmek
List<Integer> sayilar = new ArrayList<>(Arrays.asList(4, 7, 10, 13, 16)); for (Integer s : sayilar) { if (s % 2 == 0) { sayilar.remove(s); } }
Exception in thread "main" java.util.ConcurrentModificationException
Doğru: Iterator.remove()
List<Integer> sayilar = new ArrayList<>(); Collections.addAll(sayilar, 4, 7, 10, 13, 16); Iterator<Integer> it = sayilar.iterator(); while (it.hasNext()) { if (it.next() % 2 == 0) { it.remove(); // güvenli silme } } System.out.println(sayilar);
Kısa yol (Java 8+)
List<Integer> s2 = new ArrayList<>();
Collections.addAll(s2, 4, 7, 10, 13, 16);
s2.removeIf(s -> s % 2 == 0);
System.out.println(s2);[7, 13]
İki yolun çıktısı da aynı: yalnız tek sayılar kalır.
Algoritmalar
Collections Sınıfı ve Algoritmalar
Collectionbir arayüzdür;Collections(sonunda s) ise koleksiyonlar üzerinde çalışan hazırstaticmetotları toplayan bir yardımcı sınıftır.- Bu hazır algoritmalar hızlı, etkili ve test edilmiştir; kendi döngünüzü yazmak yerine bunları kullanın.
- Doğru algoritmayı seçmek performansı önemli ölçüde etkiler.
sort, reverse, reverseOrder
shuffle
binarySearch, max, min, frequency
copy, fill, swap, reverse
Algoritmalar
Temel Sıralama Algoritmaları
| Algoritma | Fikir | Ortalama | En kötü | Not |
|---|---|---|---|---|
| Kabarcık (Bubble Sort) | komşu iki öğeyi karşılaştır, gerekirse yer değiştir | O(n²) | O(n²) | basit; büyük verilerde etkisiz |
| Seçmeli (Selection Sort) | en küçüğü bul, başa yerleştir; kalanla tekrarla | O(n²) | O(n²) | büyük verilerde yavaş |
| Ekleme (Insertion Sort) | sıradaki öğeyi sıralı kısımda uygun yere ekle | O(n²) | O(n²) | küçük veya neredeyse sıralı veride etkili |
| Birleştirme (Merge Sort) | ikiye böl, her yarıyı özyinelemeli sırala, birleştir | O(n log n) | O(n log n) | kararlı; büyük verilerde etkili |
| Hızlı (Quick Sort) | pivot seç, küçükleri sola büyükleri sağa ayır (böl ve yönet) | O(n log n) | O(n²) | ortalamada çok hızlı |
Collections.sort nesneler için TimSort kullanır: birleştirme ve ekleme sıralamasının karması, kararlı, O(n log n). (Arrays.sort ilkel türlerde Dual-Pivot Quicksort kullanır.) Kararlı (stable): eşit öğelerin göreli sırası korunur.
Algoritmalar
Sıralama Metotları
List<String> isimler = new ArrayList<>(
Arrays.asList("Cem", "Ayşe", "Banu", "Ali"));
Collections.sort(isimler);
System.out.println(isimler);
Collections.sort(isimler, Collections.reverseOrder());
System.out.println(isimler);
Collections.reverse(isimler);
System.out.println(isimler);[Ali, Ayşe, Banu, Cem] [Cem, Banu, Ayşe, Ali] [Ali, Ayşe, Banu, Cem]
| Metot | Görevi |
|---|---|
sort(list) | doğal sıraya göre; öğeler Comparable olmalı |
sort(list, c) | verilen karşılaştırıcıya (Comparator) göre |
reverse(list) | listeyi ters sıraya çevirir |
String, Integer, Double gibi sınıflar zaten Comparable’dır. Java 8+: liste.sort(null) de doğal sıraya göre sıralar.
Tam imzalar: sort(List<T> list), sort(List<T> list, Comparator<? super T> c), reverse(List<?> list).
Algoritmalar
Comparable: Doğal Sıra
class Ogrenci implements Comparable<Ogrenci> { String isim; int puan; Ogrenci(String isim, int puan) { this.isim = isim; this.puan = puan; } // puana göre artan sıra @Override public int compareTo(Ogrenci diger) { return Integer.compare(puan, diger.puan); } @Override public String toString() { return isim + ":" + puan; } }
List<Ogrenci> sinif = new ArrayList<>(); sinif.add(new Ogrenci("Cem", 72)); sinif.add(new Ogrenci("Ayşe", 95)); sinif.add(new Ogrenci("Banu", 60)); Collections.sort(sinif); System.out.println(sinif);
[Banu:60, Cem:72, Ayşe:95]
- Sınıf
Comparable<Ogrenci>arayüzünü uygular vecompareTo'yu yazar. - Sonuç: negatif →
thisönce; 0 → eşit; pozitif →digerönce. Integer.compareçıkarma yapmaktan (puan − diger.puan) güvenlidir: taşma olmaz.
Algoritmalar
Comparator: Başka Bir Sıra
Collections.sort(sinif, new Comparator<Ogrenci>() { @Override public int compare(Ogrenci a, Ogrenci b) { return a.isim.compareTo(b.isim); // isme göre } }); System.out.println(sinif); // Java 8+: aynı işin kısa yazımı sinif.sort(Comparator.comparing(o -> o.puan)); System.out.println(sinif);
[Ayşe:95, Banu:60, Cem:72] [Banu:60, Cem:72, Ayşe:95]
Comparator: sınıfın dışında yazılan ayrı bir sıralama ölçütü; bir sınıf için birden çok olabilir.- Klasik yazım: anonim iç sınıf (anonymous class) ile
compare(a, b). - Java 8+:
Comparator.comparing(…)ve lambda ile tek satır; ters sıra için.reversed(). - Doğal sıra (
compareTo) değişmez; yalnızca o sıralama için başka ölçüt kullanılır.
Algoritmalar
Karıştırma
- Koleksiyon elemanlarını rastgele bir sıraya sokmak için kullanılır.
Collections.shuffle(liste)Fisher–Yates (Knuth) algoritmasını kullanır: listenin sonundan başlayarak her öğeyi rastgele seçilen bir öğeyle yer değiştirir.- Hızlı ve etkilidir: O(n). Her olası sıralama eşit olasılıkla ortaya çıkar (düzgün dağılım).
- Kullanım: kart dağıtma, kura çekme, rastgele soru sırası.
List<String> ogrenciler = new ArrayList<>(
Arrays.asList("Ali", "Banu", "Cem", "Deniz"));
Collections.shuffle(ogrenciler);
System.out.println(ogrenciler);Bir çalıştırmanın çıktısı
[Cem, Ali, Deniz, Banu]
Çıktı her çalıştırmada farklıdır. Aynı karışım için (test) sabit tohumlu new Random(42) ikinci argüman olarak verilir.
Algoritmalar
Fisher–Yates Adım Adım
Kural: i sondan 1'e kadar iner; her adımda 0 ile i arasında rastgele bir j seçilir ve a[i] ile a[j] yer değiştirir. Aşağıdaki j değerleri bir örnek çekiliştir.
Başlangıç: [A, B, C, D, E].
i = 4, rastgele j = 1: E ile B yer değiştirir. 4. konum artık kesinleşti.
i = 3, j = 3: öğe kendisiyle değişir (bu da olasıdır). Yeşil: kesinleşen konumlar.
i = 2, j = 0: A ile C yer değiştirir.
i = 1, j = 0: C ile E yer değiştirir. Sonuç: [E, C, A, D, B]; n − 1 değişim yeterli.
Algoritmalar
Loto Örneği
public class Loto { // Loto çekilişi yapan metot public static Integer[] lotoYap(int toplamSayi, int cekilecekSayi) { ArrayList<Integer> sayilar = new ArrayList<Integer>(); for (int i = 0; i < toplamSayi; i++) { sayilar.add(i + 1); // 1 … toplamSayi } Collections.shuffle(sayilar); // karıştır Integer[] cekilenSayilar = new Integer[cekilecekSayi]; for (int i = 0; i < cekilecekSayi; i++) { cekilenSayilar[i] = sayilar.get(i); } return cekilenSayilar; } public static void main(String[] args) { Integer[] sonuc = lotoYap(49, 6); // 49'dan 6 for (Integer item : sonuc) { System.out.print(item + " "); } } }
Örnek çıktı
46 18 22 11 20 10
1–49 listesi karıştırılır, ilk 6 öğe alınır: sayılar tekrarsızdır. Çıktı her çalıştırmada farklıdır.
Algoritmalar
Arama Algoritmaları
Öğeleri baştan sona tek tek kontrol eder. Sıralı olma şartı yoktur; küçük koleksiyonlarda etkilidir. O(n). Örnek: indexOf, contains.
Sıralı koleksiyonda ortadaki öğeye bakar, aranan küçükse sola, büyükse sağa gider; her adımda aralık yarıya iner. O(log n). Koleksiyon sıralı olmalıdır.
Collections.binarySearch() sıralı bir listede ikili arama yapar. 1 milyon öğede doğrusal arama 1 milyona kadar, ikili arama en fazla 20 karşılaştırma yapar.Algoritmalar
İkili Arama Adım Adım
List<Integer> sayilar = Arrays.asList(1, 3, 5, 7, 9, 11); int indeks = Collections.binarySearch(sayilar, 7); System.out.println(indeks); System.out.println(Collections.binarySearch(sayilar, 6)); System.out.println(sayilar.indexOf(7)); // doğrusal arama
7 aranıyor. low = 0, high = 5, mid = 2: 5 < 7 → sağ yarıya: low = 3.
mid = 4: 9 > 7 → sol yarıya: high = 3.
mid = 3: 7 bulundu → indeks 3 döner. Yalnızca 3 karşılaştırma.
6 aranırsa bulunamaz; 6'nın girmesi gereken yer 3'tür. Dönüş: −(3) − 1 = −4.
Çıktı
3 -4 3
Bulunamazsa dönüş negatiftir: −(ekleme noktası) − 1. Liste sıralı değilse sonuç tanımsızdır.
Algoritmalar
Kompozisyon Algoritmaları
| Metot | Görevi |
|---|---|
copy(hedef, kaynak) | kaynağın öğelerini hedefin başına kopyalar; hedef.size() ≥ kaynak.size() olmalı |
fill(liste, d) | tüm öğeleri d yapar |
reverse(liste) | öğelerin sırasını tersine çevirir |
swap(liste, i, j) | i ve j konumlarını değiştirir |
max / min | en büyük / en küçük öğe |
frequency(c, o) | o'nun kaç kez geçtiği |
List<Integer> n = Arrays.asList(4, 9, 2, 9, 5); System.out.println(Collections.max(n)); System.out.println(Collections.min(n)); System.out.println(Collections.frequency(n, 9));
9 2 2
Hedef kısa ise copy IndexOutOfBoundsException: Source does not fit in dest fırlatır.
Algoritmalar · Kodu adım adım çalıştır
Kompozisyon: İzleme
Arrays.asList sabit boyutlu bir liste; hedef ise 4 öğeli bir ArrayList.
copy: 3 öğe hedefin 0–2 konumlarına yazılır; W yerinde kalır.
reverse: sıra tersine döner.
swap(hedef, 0, 2): 0 ve 2 konumları yer değiştirir.
fill: tüm öğeler "Java" olur. Boyut değişmez.
List<String> isimler =
Arrays.asList("Ahmet", "Ayşe", "Cem");
List<String> hedef = new ArrayList<>(
Arrays.asList("X", "Y", "Z", "W"));
Collections.copy(hedef, isimler);
System.out.println(hedef);
Collections.reverse(hedef);
System.out.println(hedef);
Collections.swap(hedef, 0, 2);
System.out.println(hedef);
Collections.fill(hedef, "Java");
System.out.println(hedef);Seçim
Hangi Koleksiyonu Seçmeli?
| İhtiyaç | Seçim | Neden |
|---|---|---|
| Sıralı liste, indeksle erişim | ArrayList | hızlı get(i); varsayılan liste |
| Başa/sona sık ekleme-çıkarma, kuyruk, yığın | ArrayDeque | iki uç O(1); Stack ve LinkedList'ten hızlı |
| En öncelikli öğeyi sürekli almak | PriorityQueue | poll en küçüğü (veya ölçüte göre en önceliklisini) verir |
| Tekrarsız öğeler, hızlı “var mı?” | HashSet | contains O(1) ortalama |
| Tekrarsız + eklenme sırası | LinkedHashSet | sıra korunur |
| Tekrarsız + sıralı, aralık sorgusu | TreeSet | first, headSet, subSet |
| Anahtardan değere hızlı erişim | HashMap | get O(1) ortalama; varsayılan eşleme |
| Anahtarlar sıralı | TreeMap | firstKey, headMap, subMap |
Değişkeni arayüz türünde tanımlayın (List, Set, Map, Queue, Deque): ihtiyaç değişirse yalnızca new satırı değişir.
Özet
Özet
| Sınıf | Arayüz | Sıra | Tekrar | Temel yapı |
|---|---|---|---|---|
ArrayList | List | eklenme | evet | dinamik dizi |
LinkedList | List, Deque | eklenme | evet | çift yönlü bağlı liste |
Vector / Stack | List | eklenme / LIFO | evet | senkronize dizi (eski) |
ArrayDeque | Deque | FIFO veya LIFO | evet | dairesel dizi |
PriorityQueue | Queue | önceliğe göre çıkış | evet | ikili yığın |
HashSet | Set | garanti yok | hayır | karma tablosu |
LinkedHashSet | Set | eklenme | hayır | karma + bağlı liste |
TreeSet | NavigableSet | sıralı | hayır | kırmızı-siyah ağaç |
HashMap | Map | garanti yok | anahtar hayır | karma tablosu |
LinkedHashMap | Map | eklenme | anahtar hayır | karma + bağlı liste |
TreeMap | NavigableMap | anahtar sıralı | anahtar hayır | kırmızı-siyah ağaç |
Gezinme: for-each veya Iterator (silme için). Algoritmalar: Collections.sort, shuffle, binarySearch, copy, fill, reverse, swap.
Özet
İlgili Sayfalar
Koleksiyon çerçevesine genel bakış; List, Set, Map ve Queue örnekleri (İngilizce).
Generic sınıflar ve metotlar, sınırlı tür parametreleri, joker türler (İngilizce).
Koleksiyonlar üzerinde stream(), filter, map, collect ile işlem hatları (İngilizce).
Pratik
Sık Yapılan Hatalar (1/4)
İlkel tür ile generic
List<int> notlar = new ArrayList<>();
error: unexpected type
List<int> notlar = new ArrayList<>();
^
required: reference
found: intKoleksiyonlar nesne tutar: List<Integer> yazın. int değerler otomatik kutulanır.
Yanlış türde öğe eklemek
List<String> isimler = new ArrayList<>();
isimler.add(42);error: incompatible types: int cannot be converted to String
isimler.add(42);
^Generic tür derleme anında denetlenir. Sayıyı dizgi olarak saklamak isterseniz String.valueOf(42).
Pratik
Sık Yapılan Hatalar (2/4)
remove(int) ile remove(Object) karışması
List<Integer> liste = new ArrayList<>(); Collections.addAll(liste, 10, 20, 30); liste.remove(1); // indeks 1 System.out.println(liste); liste.remove(Integer.valueOf(10)); // değer 10 System.out.println(liste);
[10, 30] [30]
List<Integer>'da remove(1) indeks 1'i siler. Değeri silmek için Integer.valueOf(…) verin.
Integer'ları == ile karşılaştırmak
List<Integer> a = new ArrayList<>();
Collections.addAll(a, 1000, 1000);
System.out.println(a.get(0) == a.get(1));
System.out.println(a.get(0).equals(a.get(1)));false true
== referansları karşılaştırır (−128…127 arası önbellekten dolayı tesadüfen doğru çıkabilir). Değer için equals kullanın.
Pratik
Sık Yapılan Hatalar (3/4)
Arrays.asList listesine eklemek
List<Integer> sabit = Arrays.asList(1, 2, 3); sabit.add(4);
Exception in thread "main" java.lang.UnsupportedOperationException
Arrays.asList sabit boyutlu liste döndürür (set olur, add/remove olmaz). Çözüm: new ArrayList<>(Arrays.asList(…)).
Map'i doğrudan for-each ile gezmek
Map<String, Integer> m = new HashMap<>(); for (String s : m) { System.out.println(s); }
error: for-each not applicable to expression type
for (String s : m) {
^
required: array or java.lang.Iterable
found: Map<String,Integer>Map Iterable değildir: keySet(), values() veya entrySet() üzerinde gezin.
Pratik
Sık Yapılan Hatalar (4/4)
Var olmayan indeks
List<String> l = new ArrayList<>();
Collections.addAll(l, "a", "b", "c");
System.out.println(l.get(3));Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3
Geçerli indeksler 0 … size() − 1. Boş kuyrukta remove() da NoSuchElementException fırlatır; poll() null döner.
Türkçe adları sıralamak
List<String> adlar = new ArrayList<>();
Collections.addAll(adlar,
"Zeynep", "Çağla", "Can", "Ömer");
Collections.sort(adlar);
System.out.println(adlar);
Locale tr = Locale.forLanguageTag("tr-TR");
Collections.sort(adlar, Collator.getInstance(tr));
System.out.println(adlar);[Can, Zeynep, Çağla, Ömer] [Can, Çağla, Ömer, Zeynep]
String karakter kodlarıyla sıralanır: Ç, Ö, Ş, Ü, İ “Z”den sonra gelir. Türkçe alfabe sırası için Collator (java.text) kullanın.
Pratik
Örnek Problemler (1)
public class Fibonacci { public static int fibonacci(int sayi) { List<Integer> liste = new ArrayList<>(); liste.add(0); liste.add(1); for (int i = 2; i < sayi + 1; i++) { liste.add(liste.get(i - 2) + liste.get(i - 1)); } return liste.get(sayi); } public static void main(String[] args) { int sonuc = fibonacci(10); System.out.println(sonuc); } }
- Program ne yazdırır?
fibonacci(10)dönerken listede kaç öğe vardır? Son üç öğe nedir?fibonacci(1)çağrısında döngü kaç kez döner?- Bu soru için liste gerçekten gerekli mi?
Cevapları göster
- 55
- 11 öğe (indeks 0…10):
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; son üçü 21, 34, 55. - 0 kez:
i = 2için2 < 2yanlış;liste.get(1)= 1 döner. - Hayır: yalnızca son iki değeri tutan iki değişken yeterlidir (bellek O(1)). Liste, tüm diziyi saklamak gerektiğinde yararlıdır.
Pratik
Örnek Problemler (2)
public class TekrarSiz { static List<String> tekrarSiz(List<String> giris) { Set<String> gorulen = new LinkedHashSet<>(giris); return new ArrayList<>(gorulen); } public static void main(String[] args) { List<String> l = Arrays.asList("b", "a", "b", "c", "a"); System.out.println(tekrarSiz(l)); } }
- Program ne yazdırır?
LinkedHashSetyerineHashSetveyaTreeSetkullanılsaydı ne değişirdi?
Cevapları göster
- [b, a, c]: tekrarlar atılır, ilk görülme sırası korunur.
HashSet: sıra garanti edilmez.TreeSet: alfabetik,[a, b, c].
Pratik
Örnek Problemler (3)
static boolean dengeliMi(String ifade) { Deque<Character> yigin = new ArrayDeque<>(); for (char c : ifade.toCharArray()) { if (c == '(' || c == '[') { yigin.push(c); } else if (c == ')' || c == ']') { if (yigin.isEmpty()) return false; char ac = yigin.pop(); if (c == ')' && ac != '(') return false; if (c == ']' && ac != '[') return false; } } return yigin.isEmpty(); }
Parantez dengesi: her açılan parantez doğru türde ve doğru sırada kapanmalı.
dengeliMi("(a[b]c)"),dengeliMi("(a[b)c]")vedengeliMi("((")ne döndürür?- Neden yığın kullanıldı?
Cevapları göster
- true, false, false.
(a[b)c]'de)gelince üstte[vardır;((sonunda yığın boş değildir. - Son açılan parantez ilk kapanmalıdır: bu tam olarak LIFO davranışıdır.
Pratik
Örnek Problemler (4)
Deque<Integer> d = new ArrayDeque<>();
d.offerLast(1);
d.offerFirst(2);
d.offerLast(3);
d.push(4);
System.out.println(d);
System.out.println(d.pollLast() + d.pop());
System.out.println(d);Map<String, Integer> m = new TreeMap<>(); m.put("b", 1); m.put("a", 2); m.put("b", 3); Set<Integer> s = new TreeSet<>(m.values()); s.add(2); System.out.println(m + " " + s + " " + m.size());
Her iki parçanın çıktısını tahmin edin. (İpucu: push = offerFirst, pop = removeFirst.)
Cevapları göster
[4, 2, 1, 3]: 1 →[1], başa 2 →[2, 1], sona 3 →[2, 1, 3],push(4)başa →[4, 2, 1, 3].7:pollLast()3,pop()4;Integer'lar toplanır (3 + 4), sonra kalan[2, 1].{a=2, b=3} [2, 3] 2:"b"ikinciputile 3 olur; değerler {2, 3};s.add(2)tekrar olduğu için eklenmez; boyut 2.
Pratik
Alıştırmalar (1)
- Hangi koleksiyon? (a) numaradan öğrenciye hızlı erişim, (b) farklı kelimeleri alfabetik listelemek, (c) yazıcı işleri, (d) tarayıcının “geri” düğmesi, (e) acil serviste aciliyete göre çağırma.
- Bir
String[]dizisinde en sık geçen kelimeyi döndürenenSikKelimemetodunu birHashMapile yazın.
Cevapları göster
1. (a) HashMap<Integer, Ogrenci> (b) TreeSet<String> (c) Queue olarak ArrayDeque veya LinkedList (d) yığın olarak ArrayDeque (e) PriorityQueue + Comparator.
2. Yandaki çözüm su, çay, su, kahve, su, çay için su döndürür.
static String enSikKelime(String[] kelimeler) { Map<String, Integer> sayac = new HashMap<>(); for (String k : kelimeler) { sayac.put(k, sayac.getOrDefault(k, 0) + 1); } String enIyi = null; int enFazla = 0; for (Map.Entry<String, Integer> g : sayac.entrySet()) { if (g.getValue() > enFazla) { enFazla = g.getValue(); enIyi = g.getKey(); } } return enIyi; }
Pratik
Alıştırmalar (2)
- Loto çekilişini
shufflekullanmadan,Randomve birTreeSetile yazın: 1–49 arasından 6 farklı sayı, sıralı yazdırılsın.
Cevapları göster
Random r = new Random(); Set<Integer> cekilen = new TreeSet<>(); while (cekilen.size() < 6) { cekilen.add(r.nextInt(49) + 1); // 1 … 49 } System.out.println(cekilen);
[21, 27, 34, 43, 44, 45]
Örnek çıktı; her çalıştırmada farklıdır. Küme tekrarı kendisi engeller: aynı sayı gelirse add eklemez ve döngü devam eder. TreeSet sayıları sıralı tutar.
Pratik
Alıştırmalar (3)
- Her öğrencinin not listesini tutan bir
Map<String, List<Integer>>kurun; Ali: 80, 90 ve Banu: 70 için ortalamaları yazdırın.
Cevapları göster
Map<String, List<Integer>> notlar = new TreeMap<>(); notlar.put("Ali", new ArrayList<>()); notlar.get("Ali").add(80); notlar.get("Ali").add(90); notlar.put("Banu", new ArrayList<>(Arrays.asList(70))); for (Map.Entry<String, List<Integer>> g : notlar.entrySet()) { int toplam = 0; for (int n : g.getValue()) { toplam += n; } System.out.println(g.getKey() + " ort: " + toplam / g.getValue().size()); }
Ali ort: 85 Banu ort: 70
Değer bir liste olduğu için notlar.get("Ali").add(80) o listeye ekler. Ortalama tam sayı bölmesiyle hesaplandı (170 / 2 = 85).
Özet
Kaynaklar
- Oracle, The Java Tutorials: Collections (Interfaces, Implementations, Algorithms) ve Generics.
- Oracle, Java SE 21 API Documentation:
java.utilpaketi (Collection,List,Map,Collections…). - J. Gosling ve diğ., The Java Language Specification, Java SE 21 Edition (4.5 Parameterized Types, 5.1.7 Boxing Conversion, 14.14.2 Enhanced for).
- P. Deitel ve H. Deitel, Java: How to Program, 11. baskı, Pearson (Bölüm 16: Generic Collections).
- K. Sierra ve B. Bates, Head First Java, 3. baskı, O'Reilly (Bölüm 11: Data Structures).
- C. S. Horstmann, Core Java, Volume I: Fundamentals, 12. baskı, Pearson (Bölüm 9: Collections).
- M. Naftalin ve P. Wadler, Java Generics and Collections, O'Reilly.
- J. Bloch, Effective Java, 3. baskı, Addison-Wesley (Madde 11: equals ile birlikte hashCode; Madde 64: nesnelere arayüzleriyle başvurun).