---
title: 'Koleksiyon Çerçevesi'
source: 'https://academia.sh/tr/kurslar/java-standart-kutuphane/koleksiyon-cercevesi'
course: 'Standart Kütüphane ve Akışlar'
language: tr
updated: '2026-08-17T18:09:42+00:00'
license: 'CC BY-SA 4.0'
---

# Koleksiyon Çerçevesi

Aynı üç gerçekleştirim dört ayrı aile için yan yana koşturuluyor ve onbeş gözlemin yedisi arayüz garantisi, sekizi yalnız seçilen sınıfın gerçekleştirim davranışı çıkıyor. Sınırlayıcı ölçüm bu ayrımın kendisini sınırlıyor: dört ögeli bir kaynakta PriorityQueue'nun gezinme sırası çıkış sırasıyla rastlantı eseri eşleşiyor, beşinci öge eklenince ayrım yeniden görünür oluyor.

Nesneye Dayalı Java kursu boyunca bir kararı hep dil verdi. Erişim belirteci hangi üyenin
görüleceğini, `final` hangi değişkenin bir daha bağlanamayacağını, denetlenen istisna hangi
hatanın imzada duracağını derleyici belirledi. Kapanış dersi üç sözleşmenin — önceki durum,
sonraki durum, değişmez — hiçbirinin kusuru yok etmediğini, yalnız yerini değiştirdiğini
ölçtü; ama karar yine dilin içindeydi ve derleyici onu her seferinde kaynaktan okuyabiliyordu.

Bu ders yazılmış bir kütüphaneyi çağırmakla başlıyor ve karar artık dilin dışında. `List`,
`Set`, `Queue`, `Map` birer arayüzdür ve bir arayüz bir sözdür; ama o sözü kimin verdiği tek
bir yerden okunmaz. Gözlemlenen bir davranış üç kaynaktan birine ait olabilir — arayüzün
kendisine, seçilen sınıfa, ya da çağıranın uyduğu bir kurala — ve üçü çağrı yazımında hiçbir
şekilde ayırt edilemez. `ArrayList` ile `LinkedList` aynı `koy(0)` çağrısını kabul eder, aynı
`get(0)` çağrısını yanıtlar; hangi davranışın ikisinde de aynı kalacağı, hangisinin sınıf
değiştiğinde değişeceği kaynak metinden görünmez. Bu dersin ve kursun sorusu budur: elde
tutulan bir gözlemin garantisini kim veriyor.

## Üç Gerçekleştirim, Tek Soru

Sorunun yanıtı tek bir gerçekleştirimle bulunamaz — tek sınıfı gözleyen biri onun
davranışını arayüzün sözüyle karıştırır. Ölçüm bu yüzden aynı arayüzü konuşan **üç**
gerçekleştirimi yan yana koyar ve üçüne aynı soruyu sorar: yanıt üçünde de aynıysa gözlem
arayüzden geliyordur, üçü ayrışıyorsa gözlem gerçekleştirime aittir.

- **KO1** — Aşağıdaki `Garanti` sınıfı hiçbir aileye özgü değildir. `sor` yalnızca topladığı
  yanıtları karşılaştırır; liste, küme, kuyruk ya da sözlük olması ölçütü değiştirmez.
- **KO2** — Bir gerçekleştirim çağrı sırasında istisna fırlatırsa yanıtı `"hata"` sayılır ve
  öteki iki yanıtla aynı sütunda karşılaştırılır; istisna ayrı bir dal açmaz.

```java
// Garanti.java — bir davranisin garantisini kim veriyor: arayuz mu, gerceklestirim mi
import java.util.*;
import java.util.function.*;

public class Garanti {
    static int arayuz = 0;
    static int gerceklestirim = 0;

    final List<String> adlar = new ArrayList<>();
    final List<Supplier<Object>> uretecler = new ArrayList<>();

    Garanti ekle(String ad, Supplier<Object> uretec) {
        adlar.add(ad);
        uretecler.add(uretec);
        return this;
    }

    void baslik(String aile) {
        StringBuilder sb = new StringBuilder(String.format("%-32s", aile));
        for (String ad : adlar) sb.append(String.format("%-15s", ad));
        sb.append("garantiyi veren");
        System.out.println(sb);
    }

    void sor(String soru, Function<Object, String> gozlem) {
        List<String> yanitlar = new ArrayList<>();
        for (Supplier<Object> u : uretecler) {
            String y;
            try {
                y = gozlem.apply(u.get());
            } catch (RuntimeException e) {
                y = "hata";
            }
            yanitlar.add(y);
        }
        boolean ortak = new HashSet<>(yanitlar).size() == 1;
        if (ortak) arayuz++; else gerceklestirim++;
        StringBuilder sb = new StringBuilder(String.format("%-32s", soru));
        for (String y : yanitlar) sb.append(String.format("%-15s", y));
        sb.append(ortak ? "arayuz" : "gerceklestirim");
        System.out.println(sb);
    }

    static void ozet() {
        System.out.printf("gozlem: %d arayuz garantisi, %d gerceklestirim davranisi%n",
                arayuz, gerceklestirim);
    }
}
```

`ekle` bir aileye bir gerçekleştirim ekler; her aile üç kez çağırır. `sor` bir soruyu üç
gerçekleştirime birden sorar ve tek bir sayaç işletir: yanıtlar kümesi tek elemana
düşüyorsa (`HashSet<>(yanitlar).size() == 1`) soru arayüz sütununa, düşmüyorsa gerçekleştirim
sütununa yazılır. Kural mekanik ve öznesizdir — hangi ailenin sorulduğunu bilmez, yalnız
yanıtları sayar.

## Dört Aile, On Beş Gözlem

- **KO3** — Kaynak liste `KAYNAK` beş sabit ögedir ve dört aile boyunca değişmeden kalır;
  sözlük doldurulurken de aynı sırayla yazılır.
- **KO4** — Sayılan onbeş satırın hepsi aynı programın tek koşumundan gelir; `ozet` bu
  koşumun toplamını, başka hiçbir satırı saymadan, verir.

```java
// Cerceve.java — dort ailenin gozlemlenebilir sozlerini ayirir
import java.util.*;

public class Cerceve {
    static final List<String> KAYNAK = List.of("zulu", "delta", "alfa", "carli", "bravo");

    static Map<String, Integer> doldur(Map<String, Integer> m) {
        for (int i = 0; i < KAYNAK.size(); i++) m.put(KAYNAK.get(i), i);
        return m;
    }

    @SuppressWarnings("unchecked")
    public static void main(String[] args) {
        Garanti liste = new Garanti()
                .ekle("ArrayList", () -> new ArrayList<>(KAYNAK))
                .ekle("LinkedList", () -> new LinkedList<>(KAYNAK))
                .ekle("List.of", () -> List.copyOf(KAYNAK));
        liste.baslik("liste");
        liste.sor("ekleme sirasi korunuyor mu",
                o -> String.valueOf(new ArrayList<>((List<String>) o).equals(KAYNAK)));
        liste.sor("indeksle erisim var mi", o -> ((List<String>) o).get(1));
        liste.sor("esitlik icerige mi bakiyor",
                o -> String.valueOf(o.equals(new ArrayList<>(KAYNAK))));
        liste.sor("oge eklenebiliyor mu", o -> {
            try { ((List<String>) o).add("ekstra"); return "evet"; }
            catch (RuntimeException e) { return "hayir"; }
        });
        liste.sor("bos deger tutulabiliyor mu", o -> {
            try { ((List<String>) o).add(null); return "evet"; }
            catch (RuntimeException e) { return "hayir"; }
        });
        System.out.println();

        Garanti kume = new Garanti()
                .ekle("HashSet", () -> new HashSet<>(KAYNAK))
                .ekle("LinkedHashSet", () -> new LinkedHashSet<>(KAYNAK))
                .ekle("TreeSet", () -> new TreeSet<>(KAYNAK));
        kume.baslik("kume");
        kume.sor("yinelenen oge kabul ediliyor mu", o -> {
            Set<String> s = (Set<String>) o;
            s.add("alfa");
            return String.valueOf(s.size());
        });
        kume.sor("gezinme sirasi ekleme sirasi mi",
                o -> String.valueOf(new ArrayList<>((Set<String>) o).equals(KAYNAK)));
        kume.sor("bos deger kabul ediliyor mu", o -> {
            try { ((Set<String>) o).add(null); return "evet"; }
            catch (RuntimeException e) { return "hayir"; }
        });
        System.out.println();

        Garanti kuyruk = new Garanti()
                .ekle("ArrayDeque", () -> new ArrayDeque<>(KAYNAK))
                .ekle("LinkedList", () -> new LinkedList<>(KAYNAK))
                .ekle("PriorityQueue", () -> new PriorityQueue<>(KAYNAK));
        kuyruk.baslik("kuyruk");
        kuyruk.sor("bastan cikan oge", o -> ((Queue<String>) o).poll());
        kuyruk.sor("bosalinca ne donuyor", o -> {
            Queue<String> q = (Queue<String>) o;
            while (q.poll() != null) { }
            return String.valueOf(q.poll());
        });
        kuyruk.sor("gezinme sirasi cikis sirasi mi", o -> {
            Queue<String> q = (Queue<String>) o;
            List<String> gezinme = new ArrayList<>(q);
            List<String> cikis = new ArrayList<>();
            String s;
            while ((s = q.poll()) != null) cikis.add(s);
            return String.valueOf(gezinme.equals(cikis));
        });
        System.out.println();

        Garanti sozluk = new Garanti()
                .ekle("HashMap", () -> doldur(new HashMap<>()))
                .ekle("LinkedHashMap", () -> doldur(new LinkedHashMap<>()))
                .ekle("TreeMap", () -> doldur(new TreeMap<>()));
        sozluk.baslik("sozluk");
        sozluk.sor("anahtar tekil mi", o -> {
            Map<String, Integer> m = (Map<String, Integer>) o;
            m.put("alfa", 99);
            return String.valueOf(m.size());
        });
        sozluk.sor("anahtar gorunumu canli mi", o -> {
            Map<String, Integer> m = (Map<String, Integer>) o;
            Set<String> g = m.keySet();
            m.put("ekstra", 5);
            return String.valueOf(g.contains("ekstra"));
        });
        sozluk.sor("gezinme sirasi ekleme sirasi mi",
                o -> String.valueOf(new ArrayList<>(((Map<String, Integer>) o).keySet())
                        .equals(KAYNAK)));
        sozluk.sor("bos anahtar kabul ediliyor mu", o -> {
            try { ((Map<String, Integer>) o).put(null, 0); return "evet"; }
            catch (RuntimeException e) { return "hayir"; }
        });
        System.out.println();

        Garanti.ozet();
    }
}
```

```
liste                           ArrayList      LinkedList     List.of        garantiyi veren
ekleme sirasi korunuyor mu      true           true           true           arayuz
indeksle erisim var mi          delta          delta          delta          arayuz
esitlik icerige mi bakiyor      true           true           true           arayuz
oge eklenebiliyor mu            evet           evet           hayir          gerceklestirim
bos deger tutulabiliyor mu      evet           evet           hayir          gerceklestirim

kume                            HashSet        LinkedHashSet  TreeSet        garantiyi veren
yinelenen oge kabul ediliyor mu 5              5              5              arayuz
gezinme sirasi ekleme sirasi mi false          true           false          gerceklestirim
bos deger kabul ediliyor mu     evet           evet           hayir          gerceklestirim

kuyruk                          ArrayDeque     LinkedList     PriorityQueue  garantiyi veren
bastan cikan oge                zulu           zulu           alfa           gerceklestirim
bosalinca ne donuyor            null           null           null           arayuz
gezinme sirasi cikis sirasi mi  true           true           false          gerceklestirim

sozluk                          HashMap        LinkedHashMap  TreeMap        garantiyi veren
anahtar tekil mi                5              5              5              arayuz
anahtar gorunumu canli mi       true           true           true           arayuz
gezinme sirasi ekleme sirasi mi false          true           false          gerceklestirim
bos anahtar kabul ediliyor mu   evet           evet           hayir          gerceklestirim

gozlem: 7 arayuz garantisi, 8 gerceklestirim davranisi
```

Onbeş satırın **yedisi** arayüz sütununda, **sekizi** gerçekleştirim sütununda topladı.
Ayrım rastgele değildir ve tabloyu ikiye bölen bir çizgi çizilebilir: **ne tutulduğu**
arayüzde durur, **nasıl ve hangi sırayla tutulduğu** gerçekleştirime bırakılmıştır. Bir
listenin ekleme sırasını koruyacağı, içindekini indeksle vereceği, eşitliğinin içeriğe
bakacağı — üçü de üç sınıfta aynı. Aynı ögenin ikinci kez eklenmesinin kümeyi büyütmeyeceği,
boş bir kuyruktan çekmenin `null` vereceği — bunlar da öyle. Buna karşılık bir kümenin veya
sözlüğün hangi sırayla gezileceği, bir kuyruğun başından hangi ögenin çıkacağı, bir kabın
boş değeri kabul edip etmeyeceği satır satır ayrışıyor. Tek bir sınıfı — yalnızca
`HashMap`'i, yalnızca `PriorityQueue`'yu — gözleyerek çıkarılan bir davranış listesinin
**çoğunluğu**, arayüzün verdiği söz değildir.

## İsteğe Bağlı İşlem: Arayüzün Kendi Çekincesi

Tablodaki iki satır ayrı bir okumayı hak ediyor: "öge eklenebiliyor mu" ve "bos deger
tutulabiliyor mu" ikisi de `gerceklestirim` diye işaretlendi, çünkü `List.of` ile üretilen
kap ikisini de reddediyor, `ArrayList` ile `LinkedList` ikisini de kabul ediyor. Ama
`Collection` arayüzünün kendi tanımı `add` yöntemini **isteğe bağlı işlem** (optional
operation) diye adlandırır: arayüz yöntemi tanımlar, aynı zamanda bir gerçekleştirimin onu
reddedebileceğini de söyler. Bu, garanti sorusunu ikiye ayırıyor — çağrının **başarılı
olup olmayacağı** ayrı bir sorudur, **başarısız olduğunda ne olacağı** ayrı bir sorudur.
Birincisinin yanıtı yukarıdaki tabloda gerçekleştirime bağlıydı; ikincisi aşağıda ölçülüyor.

- **KO5** — Dört kap türü aynı denemeyi paylaşır: tek bir öge eklemeyi dene, reddedilirse
  istisnanın sınıf adını yaz, kabul edilirse `"basarili"` yaz.

```java
// IsteyeBagli.java — reddeden gerceklestirimlerin hepsi ayni istisnayi mi atiyor
import java.util.*;

public class IsteyeBagli {
    static String dene(Runnable islem) {
        try { islem.run(); return "basarili"; }
        catch (RuntimeException e) { return e.getClass().getSimpleName(); }
    }

    public static void main(String[] args) {
        List<String> degisebilirListe = new ArrayList<>(List.of("a"));
        List<String> sabitListe = List.of("a");
        Set<String> sabitKume = Set.of("a");
        Map<String, Integer> sabitSozluk = Map.of("a", 1);

        System.out.println("ArrayList.add     : " + dene(() -> degisebilirListe.add("b")));
        System.out.println("List.of(...).add  : " + dene(() -> sabitListe.add("b")));
        System.out.println("Set.of(...).add   : " + dene(() -> sabitKume.add("b")));
        System.out.println("Map.of(...).put   : " + dene(() -> sabitSozluk.put("b", 2)));
    }
}
```

```
ArrayList.add     : basarili
List.of(...).add  : UnsupportedOperationException
Set.of(...).add   : UnsupportedOperationException
Map.of(...).put   : UnsupportedOperationException
```

Üç ayrı kap türü, üç ayrı paket, aynı reddi aynı sınıfla veriyor. Bu satır yukarıdaki
tabloya girseydi ortak yanıt yüzünden `arayuz` diye işaretlenirdi — oysa reddin **kendisi**
`ArrayList` için hiç gerçekleşmiyor, yalnız üç sabit kap için gerçekleşiyor. Çelişki
görünüşte kalıyor, çünkü iki ayrı soru karışıyor. "Ekleme kabul edilir mi" sorusunun
yanıtı gerçekleştirime bağlıdır ve önceki tabloda öyle sayıldı. "Kabul edilmezse hangi
istisna düşer" sorusunun yanıtı ise `Collection` arayüzünün javadoc'unda adı geçen tek bir
sınıfa bağlanmıştır ve üç paket boyunca değişmiyor. Arayüz burada bir davranışı garanti
etmiyor, bir **reddin biçimini** garanti ediyor: reddeden her gerçekleştirim aynı adla,
denetlenmeyen aynı istisna sınıfıyla reddediyor. Bu, "isteğe bağlı işlem" ifadesinin neden
"işlem yoktur" değil "işlem olabilir ya da adıyla düşer" anlamına geldiğini gösteriyor.

## Sınırlayıcı Ölçüm: Birlik Zayıf Kanıttır

Çerçevenin kuralı basit bir çıkarımdır: üç yanıt aynıysa arayüz. Bu bir **çıkarımdır**,
belgeye bakmaz — ve çıkarımın kendisi yanılabilir. Kuyruk tablosundaki üçüncü satır
(`gezinme sirasi cikis sirasi mi`) `PriorityQueue` için `false` verdi; `ArrayDeque` ile
`LinkedList` içinse `true`. Bu satırın beş ögeli kaynakla ayrıştığı zaten görüldü. Aynı
soru dört ögeli, daha küçük bir kaynağa sorulursa ne olur.

- **KO6** — Dört ögeli kaynak, beş ögeli `KAYNAK`'ın ilk ögesi (`zulu`) çıkarılmış hâlidir;
  beşinci öge geri eklendiğinde kaynak yeniden birebir `KAYNAK`'a döner.

```java
// Rastlanti.java — gozlem birligi garanti kaniti degil
import java.util.*;

public class Rastlanti {
    static final List<String> KAYNAK = List.of("zulu", "delta", "alfa", "carli", "bravo");

    static boolean gezinmeCikisaEsitMi(List<String> kaynak) {
        PriorityQueue<String> pq = new PriorityQueue<>(kaynak);
        List<String> gezinme = new ArrayList<>(pq);
        List<String> cikis = new ArrayList<>();
        String s;
        while ((s = pq.poll()) != null) cikis.add(s);
        return gezinme.equals(cikis);
    }

    public static void main(String[] args) {
        List<String> dortOgeli = KAYNAK.subList(1, 5);
        System.out.println("dort ogeli kaynak              : " + dortOgeli);
        System.out.println("gezinme sirasi cikis sirasi mi : " + gezinmeCikisaEsitMi(dortOgeli));

        List<String> besOgeli = new ArrayList<>(dortOgeli);
        besOgeli.add(0, "zulu");
        System.out.println("besinci oge eklenince kaynak   : " + besOgeli);
        System.out.println("gezinme sirasi cikis sirasi mi : " + gezinmeCikisaEsitMi(besOgeli));
    }
}
```

```
dort ogeli kaynak              : [delta, alfa, carli, bravo]
gezinme sirasi cikis sirasi mi : true
besinci oge eklenince kaynak   : [zulu, delta, alfa, carli, bravo]
gezinme sirasi cikis sirasi mi : false
```

Dört ögelik kaynakla `PriorityQueue`'nun gezinme sırası çıkış sırasıyla **birebir eşleşiyor**
— çıkarımın kuralına göre bu bir arayüz garantisi olurdu. Ama beşinci öge eklenip kaynak
yeniden `KAYNAK`'ın kendisi olduğunda aynı soru `false` veriyor: kuyruk tablosunda zaten
görülen sonuç. Aradaki tek fark ögelerin kendisidir; kuyruk arayüzü gezinme sırası için hiçbir
zaman söz vermedi, ne dört ögede ne beşte. Dört ögelik durumda ortaya çıkan eşleşme kütüphanenin
verdiği bir söz değil, o beş ismin heap dizilimiyle rastlantı eseri örtüşmesiydi.

Ders boyunca kurulan ölçütü tersinden okumanın yolu budur: **birlik gözlemi garantiyi zayıf
biçimde destekler, ayrılık gözlemi garantisizliği kesin gösterir.** Üç gerçekleştirimin aynı
yanıtı vermesi bir arayüz sözü olabileceği gibi, veri kümesinin küçüklüğünden doğan bir
rastlantı da olabilir; bunu ayırt etmenin tek yolu veri kümesini değiştirip aynı soruyu
yeniden sormaktır. Ayrılığın kanıt gücü bundan yüksektir, çünkü hiçbir rastlantı üç ayrı
sınıfı üç ayrı yanıta zorlayamaz — ayrışan bir satır her zaman gerçek bir gerçekleştirim
farkını gösterir.

## Özet

- Bir davranışın garantisini kimin verdiği çağrı yazımından görünmez; üç gerçekleştirimi
  yan yana koşturup yanıtları karşılaştırmak gerekir. Yanıt üçünde aynıysa gözlem arayüzden,
  ayrışıyorsa seçilen sınıftan geliyordur.
- Dört ailede (liste, küme, kuyruk, sözlük) sorulan onbeş sorunun **yedisi** arayüz
  garantisi, **sekizi** gerçekleştirim davranışı çıktı. Ne tutulduğu arayüzde durur, nasıl
  ve hangi sırayla tutulduğu gerçekleştirime bırakılır.
- `Collection` arayüzü `add` gibi yöntemleri isteğe bağlı işlem diye tanımlar: kabul edilip
  edilmeyeceği gerçekleştirime bağlıdır, ama reddedildiğinde hangi istisnanın düşeceği üç
  ayrı paket boyunca aynı kalır — reddin kendisi değil, reddin **biçimi** arayüzün sözüdür.
- Sınırlayıcı ölçüm: dört ögeli bir kaynakta `PriorityQueue`'nun gezinme sırası çıkış
  sırasıyla rastlantı eseri eşleşir; beşinci öge eklendiğinde ayrım yeniden görünür olur.
  Gözlem birliği garanti kanıtı değildir, ayrılık gözlemi garantisizliği kesin gösterir.
- `Olcek` çekirdeği (sınıf dosyasından bilgi okuma aracı) bu derste kullanılmadı; ölçüm
  yalnız çalışma zamanı gözlemine dayanıyor, çünkü sorulan soru derleyicinin değil
  kütüphanenin verdiği sözle ilgili.

## Sonraki Adım

Bu derste dört aile bir bütün olarak ölçüldü ve her birinin kaç sözünün arayüzden geldiği
sayıldı. Ama "liste", "küme" ve "kuyruk" ayrımının kendisi hiç sorgulanmadı — üçü de birer
koleksiyondur, üçü de aynı iş yükünü kabul edebilir. Sıradaki ders aynı veriyi üç arayüze
birden verip her birinin **hangi sözü verdiğini ve hangi bilgiyi sessizce düşürdüğünü**
ölçer; `LinkedList`'in hem liste hem kuyruk olmasının aynı çağrıya iki ayrı anlam
kazandırdığı da orada görülür.
