Bölüm 5: Koleksiyonlar

Java ile Nesne Yönelimli Programlama
Koleksiyon çerçevesiGeneric türlerArrayList ve LinkedListVector ve Stack Queue ve PriorityQueueDeque ve ArrayDequeSet: HashSet, TreeSetMap: HashMap, TreeMap IteratorSıralama ve aramaKarıştırma ve kompozisyon
Sercan KÜLCÜ · Giresun Üniversitesi · Elektrik-Elektronik Mühendisliği

Giriş

Öğrenme Çıktıları

Çerçeve

Koleksiyon çerçevesinin arayüz, uygulama ve algoritma unsurlarını ve arayüz/sınıf hiyerarşisini açıklamak.

Generic türler

List<String> gibi generic türlerle tip güvenli kod yazmak; sarmalayıcı sınıfları ve otomatik kutulamayı kullanmak.

Listeler

ArrayList, LinkedList, Vector ve Stack'i kullanmak; performans farklarını açıklamak.

Kuyruklar

Queue, PriorityQueue ve ArrayDeque ile FIFO, öncelik ve LIFO davranışlarını gerçeklemek.

Küme ve eşlemeler

HashSet, TreeSet, HashMap, TreeMap ve bağlantılı sürümlerini doğru yerde seçmek.

Gezinme ve algoritmalar

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.util paketindeki 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, contains gibi 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
Benzetme: dizi koltuk sayısı sabit bir otobüs; ArrayList yolcu arttıkça büyüyen bir otobüstür.

Koleksiyon Çerçevesi

Koleksiyon Türleri

List (liste)

Sıralı, indeksli öğeler; tekrar olabilir. ArrayList, LinkedList

AliCanAliEce
Set (küme)

Yalnızca tekil öğeler; aynı öğe ikinci kez eklenmez. HashSet, TreeSet

AliCanEce
Map (eşleme)

Anahtar → değer çiftleri; her anahtar bir kez. HashMap, TreeMap

Ali → 85Can → 72
Queue (kuyruk)

İşlenmeyi bekleyen öğeler; genellikle ilk giren ilk çıkar (FIFO). LinkedList, PriorityQueue

baş: AliCanEce: son

Koleksiyon Çerçevesi

Temel İşlemler ve Tasarım Amaçları

Temel işlemler

Ekleme, çıkarma, güncelleme ve arama; for-each döngüsüyle kolay gezinme (iterasyon).

Kolay kullanım

Basit ve anlaşılır bir API: kod daha okunur olur, bakımı kolaylaşır.

Performans

Veri hacmine ve erişim ihtiyacına göre optimize edilmiş, bellek açısından verimli yapılar.

Tip güvenliği

Generic yapılar (List<String>) yanlış türdeki öğeyi derleme anında yakalar.

Geniş hiyerarşi

Farklı ihtiyaçlar için bir sınıf ailesi; standart kütüphanenin geri kalanıyla uyumlu çalışır.

Hazır algoritmalar

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

«interface»Iterable«interface»Collection«interface»List«interface»Queue«interface»Set«interface»Mapayrı hiyerarşi(Collection değil)
  • Iterable: for-each ile 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 ama Collection'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ı

«interface»Collection«interface»List«interface»Queue«interface»SetArrayListVectorStackLinkedListPriorityQueue«interface»DequeArrayDequeHashSetLinkedHashSet«interface»SortedSet«interface»NavigableSetTreeSetarayüzsınıfextends (türer)implements (uygular)

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

Arayüz (Interface)

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.

Uygulama (Implementation)

Arayüzü uygulayan gerçek sınıftır (nasıl yapılır). Örnek: ArrayList, List'i dinamik bir diziyle uygular.

Algoritma (Algorithm)

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]
Modüler tasarım: her bileşenin belirli bir rolü ve sorumluluğu vardır. Esneklik: farklı uygulamalar ve algoritmalar aynı arayüz üzerinden birlikte kullanılabilir.

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: ArrayList dinamik dizi, LinkedList çift yönlü bağlı liste, HashMap anahtar-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; get sonucu 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ürSarmalayıcı sınıf
intInteger
doubleDouble
charCharacter
booleanBoolean
longLong

İ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; add sona ekler.
  • Telefon rehberi: HashMap bir anahtarı (isim) bir değere (numara) eşler.
  • put(anahtar, değer) ile ekleriz, get(anahtar) ile değeri buluruz.
  • Listeyi println ile yazdırmak öğeleri [ … ] içinde gösterir.

Koleksiyon Çerçevesi

Collection Arayüzü Metotları

MetotGöreviDöndürür
add(E e)öğeyi koleksiyona eklerboolean: eklendiyse true
remove(Object o)öğeyi koleksiyondan çıkarırboolean
size()eleman sayısını verirint
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ürObject[]
iterator()gezinmek için bir yineleyici verirIterator<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 (indeksli get yok).
  • 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; yerine ArrayList tercih edilir.
MetotGö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.
  • AbstractList sınıfından türetilmiştir ve List arayü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
O(1): süre eleman sayısından bağımsız (sabit). O(n): süre eleman sayısı n ile orantılı.

Listeler

ArrayList Nasıl Büyür?

iç dizi (elemanlar)A0B1C23size = 3, kapasite = 4

new ArrayList<>(4) ile başlangıç kapasitesi 4 olan bir liste düşünelim: içeride 4 hücrelik bir dizi var, 3'ü dolu.

iç dizi (elemanlar)A0B1C2D3size = 4, kapasite = 4 (dolu)

add("D"): boş hücre var; D doğrudan sona yazılır. Hiçbir öğe taşınmaz: O(1).

iç dizi (elemanlar)A0B1C2D3yeni dizi: kapasite 4 + 4/2 = 6A0B1C2D3454 öğe kopyalanır

add("E"): dizi dolu! Daha büyük yeni bir dizi ayrılır ve eski 4 öğe tek tek kopyalanır: O(n).

iç dizi (elemanlar)A0B1C2D3eski dizi: artık kullanılmıyoryeni dizi: kapasite 4 + 4/2 = 6A0B1C2D3E45size = 5, kapasite = 6

E yeni dizinin 4. hücresine yazılır. Eski dizi çöp toplayıcıya (garbage collector) bırakılır.

Varsayılan kapasite 10'dur; her büyümede yaklaşık 1,5 katına çıkar. Kopyalama yalnızca arada bir yapıldığı için sona ekleme ortalamada (amortize) O(1) sürer. Kapasite size() değildir: size() dolu hücre sayısıdır.

Listeler · Kodu adım adım çalıştır

ArrayList Metotları: İzleme

isimlersize = 0boş liste

Boş bir ArrayList oluşur: size() 0.

isimlersize = 1Ali0

add öğeyi sona ekler: Ali 0. indekste.

isimlersize = 5Ali0Banu1Cem2Deniz3Ece4

Dört öğe daha sona eklenir; indeksler 0…4.

isimlersize = 5Ali0Banu1Cem2Deniz3Ece4

Liste yazdırılır: öğeler eklenme sırasıyla.

isimlersize = 5Ali0Banu1Cem2Can3Ece4

set(3, "Can"): 3. indeksteki Deniz'in yerine Can yazılır. Boyut değişmez.

isimlersize = 4Ali0Banu1Cem2Can3

remove(4): 4. indeksteki Ece silinir. Son öğe olduğu için kaydırma gerekmez.

isimlersize = 5Ali0Banu1Fatma2Cem3Can4

add(2, "Fatma"): Cem ve Can birer sağa kayar, Fatma 2. indekse girer.

isimlersize = 5Ali0Banu1Fatma2Cem3Can4

indexOf("Banu") baştan arar ve ilk konumu döndürür: 1.

isimlersize = 5Ali0Banu1Fatma2Cem3Can4

contains("Ece"): Ece daha önce silindi, sonuç false.

isimlersize = 5Ali0Banu1Fatma2Cem3Can4

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);
1002013024034

Başlangıç: [10, 20, 30, 40]. Şimdi add(1, 15) çalışacak.

10012023034043 öğe sağa

Önce 1. indeksten sonraki öğeler (sondan başlayarak) birer sağa kayar; 1. hücre boşalır.

100151202303404[10, 15, 20, 30, 40]

15 boşalan hücreye yazılır. n öğeli listede en kötü durumda n kaydırma: O(n).

1001512023034044 öğe sola

remove(0): 10 silinir, arkasındaki 4 öğe birer sola kayar.

150201302403[15, 20, 30, 40]

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.
  • AbstractSequentialList sınıfından türetilmiştir; List ve Deque arayü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).
KirazprevnextElmaprevnextArmutprevnextMuzprevnextnullnullfirstlast

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]
MetotGö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?

İşlemArrayListLinkedList
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 silmeO(n): tüm öğeler kayarO(1)
Ortaya ekleme / ortadan silmeO(n): kaydırmaO(n): konumu bulma + O(1) bağlama
Bellek kullanımıaz: yalnızca dizifazla: her düğümde 2 ek referans
Çoğu durumda ArrayList seçin. Öğe ekleme ve çıkarma işlemleri sık ve özellikle listenin uçlarında ise LinkedList (ya da kuyruk/yığın için ArrayDeque) tercih edilebilir.

Listeler

Vector Sınıfı

  • List arayü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ı ArrayList tercih 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 ekleri'deki elemanı verirelemanı çıkarıreleman 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.
  • Vector sı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 Deque arayüzünü uygulayan ArrayDeque (veya LinkedList) önerilir.

Benzetme: üst üste konmuş tabaklar; tabak hep en üstten alınır ve en üste konur.

MetotGö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ştaban

Boş bir yığın oluşur.

Aüst →taban

push("A"): A en üste konur.

ABüst →taban

push("B"): B, A'nın üstüne.

ABCüst →taban

push("C"): en üstte artık C var.

ABCüst →taban

println öğeleri alttan üste yazar: [A, B, C].

ABCüst →taban

peek() en üsttekini (C) döndürür ama çıkarmaz.

ABCüst →taban

pop() C'yi çıkarır ve döndürür: son giren ilk çıktı.

A2B1← üsttaban

search("A") konumu üstten 1'den sayar: B 1, A 2.

ABüst →taban

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 Iterator kullanı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, poll ve peek metotları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.

İşlemHata 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

çıkışboş kuyruk← giriş

Kuyruk Queue türünde, nesne LinkedList.

çıkışAlibaş = son← giriş

offer("Ali"): Ali kuyruğa girer; hem baş hem son o.

çıkışAliBanubaşson← giriş

Banu sona girer.

çıkışAliBanuCembaşson← giriş

Cem sona girer.

çıkışAliBanuCembaşson← giriş

Kuyruk baştan sona yazdırılır.

çıkışAliBanuCembaşson← giriş

peek() baştakini döndürür, çıkarmaz.

çıkışBanuCembaşsonAli← giriş

poll() baştakini çıkarır ve döndürür: ilk giren Ali ilk çıktı.

çıkışCembaş = sonBanu← giriş

Sıradaki Banu çıkar.

çıkışCembaş = son← giriş

size(): kuyrukta 1 öğe kaldı.

çıkışboş kuyrukCem← giriş

Cem de çıkar; kuyruk boşaldı.

çıkışboş kuyruk← giriş

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/poll O(log n), peek O(1); dinamik olarak büyür.
  • Kullanım: görev zamanlama, acil servis sırası, en kısa yol algoritmaları.
MetotGö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 
10[0]20[1]40[2]30[3]iç dizi:100201402303

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) ve Stack (LIFO) işlevselliğini birleştirir.
  • Uygulamalar: LinkedList (çift yönlü bağlı liste) ve ArrayDeque (dinamik dizi).
1510baş (first)son (last)addFirst / offerFirstremoveFirst / pollFirstaddLast / offerLastremoveLast / pollLast
BaşGöreviSonGörevi
addFirst(e)başa ekleraddLast(e)sona ekler
removeFirst()baştakini çıkarır, döndürürremoveLast()sondakini çıkarır, döndürür
getFirst()baştakini döndürürgetLast()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 ve Stack'ten daha hızlı ve hafiftir; yığın ve kuyruk için önerilen sınıftır.
  • null öğe kabul etmez.
MetotGö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ş

Boş bir ArrayDeque.

5baş = son

addFirst(5): 5 başa eklenir (tek öğe).

510başson

addLast(10): 10 sona eklenir.

1510başson

addFirst(1): 1 başa eklenir, 5 ve 10 yerinde kalır.

1510başson

Baştan sona yazdırılır.

510başson1

pollFirst() baştaki 1'i çıkarır; otomatik kutu açma ile int'e atanır.

5baş = son10

pollLast() sondaki 10'u çıkarır.

5baş = son

İki değer yazdırılır.

5baş = son

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 add eklemez, false dö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 da Comparator).
MetotGö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 ve Set'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.
0123456789101112131415kovalar (bucket): 0 … 15

İçte 16 kovalı bir tablo vardır (dolulukla birlikte büyür).

012muz3456789101112131415kovalar (bucket): 0 … 15"muz".hashCode() = 108498 → kova 3

add("muz"): karma değerinden kova 3 hesaplanır, muz oraya yerleşir.

012muz3elma456789101112131415kovalar (bucket): 0 … 15"elma".hashCode() = 3116155 → kova 4

add("elma"): kova 4.

012muz3elma4567kiraz89101112131415kovalar (bucket): 0 … 15"kiraz".hashCode() = 102057485 → kova 8

add("kiraz"): kova 8.

012muz3elma4567kiraz89101112131415kovalar (bucket): 0 … 15"elma".hashCode() = 3116155 → kova 4zaten var → eklenmez

İkinci add("elma"): kova 4'te equals ile eşit bir öğe var. Eklenmez; add false döner.

012muz3elma456armut7kiraz89101112131415kovalar (bucket): 0 … 15"armut".hashCode() = 93086203 → kova 7

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 HashSet kullanı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]
MetotGö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ıfGezinme sırasıTemel yapıadd / contains
HashSetgaranti yok (kova sırası)karma tablosuO(1) ortalama
LinkedHashSeteklenme sırasıkarma tablosu + bağlı listeO(1) ortalama
TreeSetsı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'in equals'ı referansları karşılaştırır) → boyut 2.
  • Nokta: equals ve hashCode geç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 bir Comparator'a göre yapılır.
  • Alt küme ve üst küme işlemleri sunar.
  • TreeSet: AbstractSet'ten türetilir, NavigableSet (dolayısıyla SortedSet) arayüzünü uygular.
  • İçte kırmızı-siyah ağaç: ekleme, silme, arama O(log n).
MetotGö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, removeekleme, çı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
AB12345A ∩ B
İşlemMetot
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 da Comparator).

Benzetme: sözlük. Kelime (anahtar) ile anlamını (değer) bulursunuz; aynı kelime iki kez yer almaz.

«interface»MapHashMapHashtable«interface»SortedMapLinkedHashMap«interface»NavigableMapTreeMap

Eşlemeler

Map Metotları

MetotGö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/put ortalama O(1).
  • AbstractMap'ten türetilmiştir ve Map'i uygular.
  • Tekil anahtarlar: aynı anahtarla put değeri değiştirir.
  • Null: bir null anahtara ve birden çok null değ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 bir Map.Entry; getKey() ve getValue() ile okunur. Hem anahtar hem değer gerekiyorsa en verimli yol budur.
  • Map doğrudan for-each'e verilemez: Iterable değildir.

Eşlemeler · Kodu adım adım çalıştır

Kelime Sayma: İzleme

anahtardeğerboş

Metin ve boş bir TreeMap hazırlanır. split(" ") metni kelimelere böler.

anahtardeğer"elma"1

"elma" ilk kez görüldü: put(k, 1).

anahtardeğer"armut"1"elma"1

"armut" ilk kez görüldü: put(k, 1).

anahtardeğer"armut"1"elma"2

"elma" zaten var: eski değer 1 alınır, 2 yazılır.

anahtardeğer"armut"1"elma"2"kiraz"1

"kiraz" ilk kez görüldü: put(k, 1).

anahtardeğer"armut"2"elma"2"kiraz"1

"armut" zaten var: eski değer 1 alınır, 2 yazılır.

anahtardeğer"armut"2"elma"3"kiraz"1

"elma" zaten var: eski değer 2 alınır, 3 yazılır.

anahtardeğer"armut"2"elma"3"kiraz"1

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 HashMap yeterlidir.
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ı: HashMap senkronize değildir; Hashtable'ın her metodu kilitlidir.
  • Anahtarlar da değerler de null olamaz.
  • Kilitleme yüzünden modern alternatiflerden yavaştır; tek iş parçacığında HashMap, çok iş parçacığında ConcurrentHashMap tercih 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, NavigableMap arayü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/put O(log n).
MetotGö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, removeMap 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

HashMapLinkedHashMapTreeMapHashtable
Gezinme sırasıgaranti yokeklenme sırasıanahtar sıralıgaranti yok
get / putO(1) ortalamaO(1) ortalamaO(log n)O(1) ortalama, kilitli
null anahtarbir tanebir tanehayırhayır
null değerevetevetevethayır
Senkronizehayırhayırhayırevet (eski)
Ne zaman?varsayılan seçimsıra korunmalısıralı anahtar, aralık sorgusueski kod
Aynı mantık kümelerde de geçerlidir: 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-each döngüsü arka planda bir Iterator kullanır.
  • Listeler için ListIterator ayrıca geriye gitmeyi, add ve set işlemlerini destekler.
MetotGö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

308152

Liste hazırlanır: [3, 8, 5].

308152imleç

iterator(): imleç ilk öğenin önüne konur.

308152imleç

hasNext() true; next() 3'ü döndürür ve imleci ilerletir.

308152imleç

Öğe yazdırılır.

308152imleç

hasNext() true; next() 8'i döndürür ve imleci ilerletir.

308152imleç

Öğe yazdırılır.

308152imleç

hasNext() true; next() 5'i döndürür ve imleci ilerletir.

308152imleç

Öğe yazdırılır.

308152imleç

İ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

  • Collection bir arayüzdür; Collections (sonunda s) ise koleksiyonlar üzerinde çalışan hazır static metotları 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.
Sıralama

sort, reverse, reverseOrder

Karıştırma

shuffle

Arama

binarySearch, max, min, frequency

Kompozisyon

copy, fill, swap, reverse

Algoritmalar

Temel Sıralama Algoritmaları

AlgoritmaFikirOrtalamaEn kötüNot
Kabarcık (Bubble Sort)komşu iki öğeyi karşılaştır, gerekirse yer değiştirO(n²)O(n²)basit; büyük verilerde etkisiz
Seçmeli (Selection Sort)en küçüğü bul, başa yerleştir; kalanla tekrarlaO(n²)O(n²)büyük verilerde yavaş
Ekleme (Insertion Sort)sıradaki öğeyi sıralı kısımda uygun yere ekleO(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ştirO(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]
MetotGö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 ve compareTo'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.

A0B1C2D3E4

Başlangıç: [A, B, C, D, E].

A0E1C2D3B4ij

i = 4, rastgele j = 1: E ile B yer değiştirir. 4. konum artık kesinleşti.

A0E1C2D3B4i = j

i = 3, j = 3: öğe kendisiyle değişir (bu da olasıdır). Yeşil: kesinleşen konumlar.

C0E1A2D3B4ij

i = 2, j = 0: A ile C yer değiştirir.

E0C1A2D3B4ij

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ı

Doğrusal arama (Linear Search)

Öğeleri baştan sona tek tek kontrol eder. Sıralı olma şartı yoktur; küçük koleksiyonlarda etkilidir. O(n). Örnek: indexOf, contains.

İkili arama (Binary Search)

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
1031527394115lowmidhigh

7 aranıyor. low = 0, high = 5, mid = 2: 5 < 7 → sağ yarıya: low = 3.

1031527394115lowmidhigh

mid = 4: 9 > 7 → sol yarıya: high = 3.

1031527394115low=mid=high

mid = 3: 7 bulundu → indeks 3 döner. Yalnızca 3 karşılaştırma.

1031527394115ekleme noktası 3

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ı

MetotGö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 / minen 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

isimlerAhmetAyşeCemhedefX0Y1Z2W3

Arrays.asList sabit boyutlu bir liste; hedef ise 4 öğeli bir ArrayList.

isimlerAhmetAyşeCemhedefAhmet0Ayşe1Cem2W3

copy: 3 öğe hedefin 0–2 konumlarına yazılır; W yerinde kalır.

isimlerAhmetAyşeCemhedefW0Cem1Ayşe2Ahmet3

reverse: sıra tersine döner.

isimlerAhmetAyşeCemhedefAyşe0Cem1W2Ahmet3

swap(hedef, 0, 2): 0 ve 2 konumları yer değiştirir.

isimlerAhmetAyşeCemhedefJava0Java1Java2Java3

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çimNeden
Sıralı liste, indeksle erişimArrayListhızlı get(i); varsayılan liste
Başa/sona sık ekleme-çıkarma, kuyruk, yığınArrayDequeiki uç O(1); Stack ve LinkedList'ten hızlı
En öncelikli öğeyi sürekli almakPriorityQueuepoll en küçüğü (veya ölçüte göre en önceliklisini) verir
Tekrarsız öğeler, hızlı “var mı?”HashSetcontains O(1) ortalama
Tekrarsız + eklenme sırasıLinkedHashSetsıra korunur
Tekrarsız + sıralı, aralık sorgusuTreeSetfirst, headSet, subSet
Anahtardan değere hızlı erişimHashMapget O(1) ortalama; varsayılan eşleme
Anahtarlar sıralıTreeMapfirstKey, 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ıfArayüzSıraTekrarTemel yapı
ArrayListListeklenmeevetdinamik dizi
LinkedListList, Dequeeklenmeevetçift yönlü bağlı liste
Vector / StackListeklenme / LIFOevetsenkronize dizi (eski)
ArrayDequeDequeFIFO veya LIFOevetdairesel dizi
PriorityQueueQueueönceliğe göre çıkışevetikili yığın
HashSetSetgaranti yokhayırkarma tablosu
LinkedHashSetSeteklenmehayırkarma + bağlı liste
TreeSetNavigableSetsıralıhayırkırmızı-siyah ağaç
HashMapMapgaranti yokanahtar hayırkarma tablosu
LinkedHashMapMapeklenmeanahtar hayırkarma + bağlı liste
TreeMapNavigableMapanahtar sıralıanahtar hayırkı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

Java Collections

Koleksiyon çerçevesine genel bakış; List, Set, Map ve Queue örnekleri (İngilizce).

Generic Programming

Generic sınıflar ve metotlar, sınırlı tür parametreleri, joker türler (İngilizce).

Java Streams

Koleksiyonlar üzerinde stream(), filter, map, collect ile işlem hatları (İngilizce).

İpucu: koleksiyonlarla çalışırken önce doğru arayüzü seçin, sonra uygulamayı. Generic türler hataları derleme anında yakalar.

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:    int

Koleksiyonlar 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);
    }
}
  1. Program ne yazdırır?
  2. fibonacci(10) dönerken listede kaç öğe vardır? Son üç öğe nedir?
  3. fibonacci(1) çağrısında döngü kaç kez döner?
  4. Bu soru için liste gerçekten gerekli mi?
Cevapları göster
  1. 55
  2. 11 öğe (indeks 0…10): [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; son üçü 21, 34, 55.
  3. 0 kez: i = 2 için 2 < 2 yanlış; liste.get(1) = 1 döner.
  4. 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));
    }
}
  1. Program ne yazdırır?
  2. LinkedHashSet yerine HashSet veya TreeSet kullanılsaydı ne değişirdi?
Cevapları göster
  1. [b, a, c]: tekrarlar atılır, ilk görülme sırası korunur.
  2. 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ı.

  1. dengeliMi("(a[b]c)"), dengeliMi("(a[b)c]") ve dengeliMi("((") ne döndürür?
  2. Neden yığın kullanıldı?
Cevapları göster
  1. true, false, false. (a[b)c]'de ) gelince üstte [ vardır; (( sonunda yığın boş değildir.
  2. 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
  1. [4, 2, 1, 3]: 1 → [1], başa 2 → [2, 1], sona 3 → [2, 1, 3], push(4) başa → [4, 2, 1, 3].
  2. 7: pollLast() 3, pop() 4; Integer'lar toplanır (3 + 4), sonra kalan [2, 1].
  3. {a=2, b=3} [2, 3] 2: "b" ikinci put ile 3 olur; değerler {2, 3}; s.add(2) tekrar olduğu için eklenmez; boyut 2.

Pratik

Alıştırmalar (1)

  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.
  2. Bir String[] dizisinde en sık geçen kelimeyi döndüren enSikKelime metodunu bir HashMap ile 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)

  1. Loto çekilişini shuffle kullanmadan, Random ve bir TreeSet ile 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)

  1. 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.util paketi (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).

Son

Bölüm 5: Koleksiyonlar
Sonraki bölüm: Bölüm 5: Dizgi (String)
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.