Java'da List, Set ve Map arasındaki fark, her birinin verinin doğasına bakış açısından kaynaklanır: List sıralı ve tekrarlı elemanları index ile tutar, Set benzersizliği garanti eden matematiksel bir küme mantığı sunar, Map ise anahtar-değer eşleşmesiyle çalışan bir sözlük gibidir. Doğru koleksiyonu seçmek, verinin tekrar edip etmediğini, sıralamanın önemli olup olmadığını ve erişimin nasıl yapılacağını netleştirmekle başlar. Bu java collection framework mantığını kavramak, ileride performans sorunlarıyla karşılaşmamak için kritik bir adımdır.
List, Set, Map Arayüzlerinin Temel Felsefi Farkı
Bir alışveriş listesi hazırladığınızı düşünün: "süt, ekmek, süt, yumurta" yazabilirsiniz; aynı ürünü iki kez yazmanız bir hata değildir, sırası da önemlidir çünkü markette hangi rafa önce gideceğinizi belirler. Java'daki List arayüzü tam olarak bu mantıkla çalışır: elemanların tekrar etmesine izin verir ve her elemana bir index numarasıyla erişilir. ArrayList veya LinkedList kullanırken listenin sırası korunur, aynı değer birden fazla kez yer alabilir ve get(2) gibi bir çağrıyla üçüncü elemana doğrudan ulaşabilirsiniz.
Set ise farklı bir dünyadan gelir: matematik derslerindeki küme kavramına çok yakındır. Bir sınıftaki öğrenci numaraları kümesini düşünün; her numara benzersizdir, aynı numara iki öğrenciye verilmez. Java'da Set arayüzü de aynı elemanın koleksiyona ikinci kez eklenmesini otomatik olarak engeller. Bu davranış, verinin doğası itibarıyla tekilliğinin garanti edilmesi gerektiği her durumda List'ten daha güvenli bir seçim sunar.
Map ise bir telefon rehberine benzer: her isim (anahtar) bir telefon numarasına (değer) karşılık gelir ve rehberde aynı isme sahip iki farklı kayıt tutmak mantıksızdır. Map arayüzü, anahtar-değer çiftleriyle çalışır; anahtar üzerinden değere hızlıca erişim sağlar ve List ile Set'ten farklı olarak tek bir eleman değil, ilişkili bir çift saklar. Bu üç yapının birbirinden ayrıldığı noktaları toplu görmek isteyenler için aşağıdaki tablo kullanışlı bir özet sunar.
| Yapı | Tekrar İzni | Sıralama Garantisi | Erişim Şekli |
|---|---|---|---|
| List | Var | Ekleme sırası korunur | Index numarasıyla |
| Set | Yok | Uygulamaya bağlı (garanti yok veya sıralı) | Eleman üzerinden (iterasyon) |
| Map | Anahtarda yok, değerde var | Uygulamaya bağlı | Anahtar üzerinden |
Bu üç arayüzün pratikte nasıl davrandığını sadece teoride okumak yerine kod yazarak deneyimlemek, kalıcı öğrenme için çok daha etkilidir. Bu noktada birebir Java özel ders programı kapsamında öğrencilerin her koleksiyon türünü küçük projelerle test etmesi, hangi yapının hangi senaryoda mantıklı olduğunu somutlaştırır. Sonuçta List, Set ve Map arasındaki seçim bir kod yazma tercihi değil, verinin gerçek hayattaki karşılığını doğru okuma meselesidir.
ArrayList mi LinkedList mi? İç Veri Yapısına Göre Performans Mantığı

ArrayList ve LinkedList aynı List arayüzünü uygularlar ama içeride birbirinden tamamen farklı çalışırlar. ArrayList, arka planda dinamik olarak büyüyebilen bir dizi kullanır; bu sayede bir elemana index numarasıyla erişmek, o elemanın bellekteki adresini doğrudan hesaplayabildiği için sabit zamanlı, yani O(1) karmaşıklığında gerçekleşir. Kitaplıktaki numaralı raflardan birini doğrudan bulmak gibidir; kaçıncı raf olduğunu bilirseniz diğer rafları kontrol etmeniz gerekmez.
LinkedList ise düğümlerden oluşan bir zincir gibidir; her düğüm kendi verisini ve bir sonraki (bazen önceki) düğümün referansını tutar. Bu yapıda üçüncü elemana ulaşmak için baştan başlayıp sırayla ilerlemeniz gerekir, bu da erişimi O(n) karmaşıklığına taşır. Ancak aynı zincir yapısı, listenin başına veya ortasına eleman eklerken avantaja dönüşür: ArrayList'te araya eleman eklemek, sonraki tüm elemanları bir konum kaydırmayı gerektirirken, LinkedList'te sadece iki düğüm arasındaki referans değiştirilir.
Bu farkı pratik bir kural haline getirmek isteyenler için basit bir ölçüt vardır: Eğer programınız verideki elemanlara sık sık index ile erişiyorsa ve ekleme-çıkarma işlemleri genellikle listenin sonunda oluyorsa ArrayList daha mantıklıdır. Buna karşılık, listenin başına veya ortasına sürekli eleman ekleyip çıkarıyorsanız ve index ile rastgele erişim ihtiyacınız azsa LinkedList'in düğüm yapısı size avantaj sağlar. Örneğin bir kuyruk (queue) simülasyonunda elemanlar sürekli baştan çıkarılıp sona ekleniyorsa LinkedList doğal bir seçim olur; ama bir öğrenci listesinde belirli bir sıradaki kaydı sürekli okuyorsanız ArrayList'in dizi tabanlı erişimi çok daha verimli çalışır.
Burada dikkat edilmesi gereken nokta, "hangisi daha hızlı" sorusunun tek bir cevabı olmamasıdır; doğru cevap her zaman "hangi işlemi daha sık yapıyorsunuz" sorusuna bağlıdır. Big-O mantığıyla düşünmek, sayısal ölçüm yapmadan önce bile hangi koleksiyonun sizin senaryonuza uygun olduğunu tahmin etmenizi sağlar.
HashSet, LinkedHashSet ve TreeSet: Sıralama ve Performans Ödünleşimi
Set arayüzünü uygulayan üç temel sınıf, aynı "tekrar yok" garantisini verirken sıralama konusunda birbirinden ayrılır. HashSet, elemanları hashCode değerine göre dağıtılmış kovalar (bucket) içinde saklar; bu sayede eleman ekleme, silme ve varlık kontrolü ortalama olarak sabit zamanlı çalışır, ancak elemanların hangi sırada tutulacağına dair hiçbir garanti vermez. Bir çekmecedeki karışık düğmeler gibidir; hepsi oradadır ama hangi sırada duracaklarını siz belirleyemezsiniz.
LinkedHashSet ise HashSet'in hızından ödün vermeden, elemanların eklenme sırasını hatırlayan bir bağlı liste yapısını da arka planda tutar. Böylece koleksiyonu döngüyle gezerken elemanları eklediğiniz sırayla görürsünüz; bu, örneğin bir kullanıcının ziyaret ettiği sayfaları tekrarsız ama kronolojik sırayla tutmak istediğinizde işe yarar.
TreeSet ise elemanları doğal sıralama düzenine (örneğin sayılar için küçükten büyüğe, metinler için alfabetik) göre otomatik olarak sıralı tutar. Bu sıralama garantisi, dengeli bir ağaç yapısı üzerinde çalıştığı için ekleme ve arama işlemlerine HashSet'e kıyasla ek bir maliyet bindirir; karmaşıklık artık sabit zamanlı değil, logaritmik zamanlıdır. Sıralı bir öğrenci numarası kümesi tutmak isterseniz TreeSet size her eklemede otomatik olarak sıralı bir çıktı verir, ama bunun karşılığında biraz daha fazla işlem yapmayı kabul etmiş olursunuz.
Hangi Set türünü seçeceğinize karar verirken şu soruları sırayla sormak işinizi kolaylaştırır:
- Elemanların hangi sırada tutulduğu sizin için hiç önemli değilse ve en yüksek performansı istiyorsanız HashSet tercih edilir.
- Sıralama önemli değil ama elemanları eklediğiniz sırayla görmek istiyorsanız LinkedHashSet uygundur.
- Elemanların her zaman belirli bir düzende (sayısal veya alfabetik) tutulmasına ihtiyacınız varsa, ek performans maliyetini kabul ederek TreeSet kullanılır.
- Sık sık aralık sorguları (belirli bir değerden büyük tüm elemanları bulma gibi) yapıyorsanız TreeSet'in sıralı yapısı size doğrudan avantaj sağlar.
Bu üç yapının hashCode ve equals metotlarıyla nasıl etkileşime girdiğini kod üzerinde denemeden tam kavramak zordur; bilginizi ölçmek isterseniz ücretsiz Java bilgi testi üzerinden kendinizi kısa sürede sınayabilirsiniz. Sonuç olarak Set seçimi, "benzersizlik" garantisinin yanına hangi sıralama davranışını eklemek istediğinize bağlı bir tercih meselesidir.
HashMap, TreeMap, LinkedHashMap: Hangi Map Ne Zaman Kullanılır
Map ailesindeki üç sınıf da anahtar-değer ilişkisi tutar, ama her biri bu ilişkiyi farklı bir mantıkla organize eder. Bunu bir telefon rehberine benzetebiliriz: HashMap isimleri rastgele sıraya koyup hızlı bulmayı önceler, TreeMap isimleri alfabetik dizer, LinkedHashMap ise kişileri kaydettiğin sırayla listeler. HashMap, sıralamanın hiç önemli olmadığı ve önceliğin sadece hızlı erişim olduğu durumlarda tercih edilir; bir kullanıcı kimliğine karşılık gelen oturum bilgisini tutmak gibi senaryolarda anahtarın hangi sırada durduğu kimseyi ilgilendirmez, önemli olan anahtarı verince değeri anında almaktır.
TreeMap devreye girdiğinde iş değişir. Anahtarlara göre sıralı gezinme gerektiren durumlarda — örneğin öğrenci numaralarını küçükten büyüğe doğru işlemek veya bir tarih aralığındaki kayıtları sırayla raporlamak istediğinizde — TreeMap anahtarları otomatik olarak sıralı tutar ve bu sıralı yapı üzerinde gezinmeyi doğrudan destekler. Bu güvenceyi elde etmek için TreeMap, her ekleme ve arama işleminde sıralı bir ağaç yapısını güncel tutmak zorundadır; dolayısıyla HashMap'e göre biraz daha fazla iş yapar ama karşılığında sıralama garantisi verir.
LinkedHashMap ise farklı bir problemi çözer: ekleme sırasının korunması gerektiği durumlar. Bir e-ticaret sitesinde kullanıcının son bakılan ürünlerini veya bir günlük dosyasında işlemlerin gerçekleştiği sırayı tutmak istediğinizde, anahtarların alfabetik veya sayısal sıralanması işe yaramaz; asıl önemli olan hangi kaydın önce, hangisinin sonra eklendiğidir. LinkedHashMap bu ekleme sırasını korurken HashMap'in hızlı erişim mantığını da büyük ölçüde sürdürür, bu yüzden "sıralama önemli ama alfabetik değil, kronolojik olsun" denen her yerde doğal bir çözümdür.
Bu üç yapının List ve Set ile birlikte aynı veri üzerinde nasıl farklı davrandığını görmek, teoriyi somutlaştırmanın en etkili yoludur. Aşağıdaki örnek, aynı tekrarlı veriyi bir ArrayList'e, bir HashSet'e ve bir HashMap'e eklediğimizde her yapının kendi karakterine göre nasıl tepki verdiğini gösterir:
import java.util.*;
public class KoleksiyonKarsilastirma {
public static void main(String[] args) {
List<String> liste = new ArrayList<>();
Set<String> kume = new HashSet<>();
Map<String, Integer> harita = new HashMap<>();
String[] veri = {"ali", "veli", "ali", "ayse", "veli"};
for (String isim : veri) {
liste.add(isim);
kume.add(isim);
harita.put(isim, harita.getOrDefault(isim, 0) + 1);
}
System.out.println("ArrayList (tüm tekrarlar): " + liste);
System.out.println("HashSet (tekilleştirilmiş): " + kume);
System.out.println("HashMap (isim -> tekrar sayısı): " + harita);
}
}
Bu kod çalıştırıldığında ArrayList, gelen beş elemanın hepsini sırasıyla ve tekrarlarıyla birlikte saklar; HashSet aynı veriden yalnızca benzersiz isimleri tutar çünkü Set felsefesi tekrara izin vermez; HashMap ise her ismi bir sayaçla eşleştirerek "kaç kez geçti" bilgisini doğrudan üretir. Aynı ham veri, üç farklı yapıda üç farklı soruya cevap verir; doğru koleksiyonu seçmek, aslında hangi soruyu sorduğunuzu netleştirmektir.
Sık Yapılan Yanlış Koleksiyon Seçimi Hataları

Koleksiyon seçiminde yapılan hataların büyük kısmı, kodun çalışmamasından değil, çalışıp da yavaş veya hatalı sonuç üretmesinden kaynaklanır. Bu hatalar genellikle ilk bakışta fark edilmez, veri büyüdükçe veya belirli bir senaryoda ortaya çıkar. Aşağıdaki liste, öğrencilerin ve hatta deneyimli geliştiricilerin sıkça düştüğü tuzakları özetler:
- Sık arama yapılan yerde List kullanmak: Binlerce kayıt arasında belirli bir elemanı sürekli
contains()ile aramak için ArrayList veya LinkedList kullanmak, her aramada listenin baştan sona taranmasına yol açar. Aynı arama işlemi bir HashSet veya HashMap üzerinde yapıldığında hash tablosu sayesinde çok daha hızlı sonuçlanır; List burada yanlış araç seçimidir. - Gerek yokken TreeMap veya TreeSet seçmek: Sıralamaya hiç ihtiyaç olmayan bir senaryoda, sadece "belki ileride sıralı gerekir" düşüncesiyle TreeMap veya TreeSet kullanmak, her ekleme ve aramada gereksiz bir sıralama maliyeti ödemek demektir. Sıralama fiilen kullanılmıyorsa HashMap veya HashSet aynı işi daha az işlemle yapar.
- hashCode ve equals metodlarını doğru override etmemek: Kendi tanımladığınız bir sınıfın nesnelerini HashSet'e veya HashMap'in anahtarı olarak koyarken bu iki metodu birlikte ve tutarlı biçimde ezmezseniz, mantıken aynı olan iki nesne Java tarafından farklı kabul edilir. Bu durumda Set'e "aynı" veri iki kez eklenmiş gibi görünür ve tekilleştirme beklentisi tamamen boşa çıkar.
- LinkedHashMap yerine HashMap kullanıp sıra bekleme: HashMap'in eleman sırasını korumadığını unutup, bir işlem geçmişini veya son eklenenler listesini HashMap ile tutmaya çalışmak, çıktının beklenmedik bir sırada görünmesine neden olur.
Bu hataların çoğu, koleksiyonun iç mantığını değil sadece adını ezberlemekten doğar. Kendi seviyenizi ölçmek ve bu tür kavramsal boşlukları görmek isteyenler ücretsiz kodlama bilgisi testi ile hangi konularda daha çok pratiğe ihtiyaç duyduklarını hızlıca fark edebilir.
Doğru Koleksiyon Seçimi İçin Karar Verme Kriterleri
Koleksiyon seçimini ezbere değil, birbirini takip eden birkaç soruya verilen cevaba göre yapmak, hem daha hızlı hem de daha az hataya açık bir yöntemdir. Aşağıdaki adımlar, bir veri yapısı seçerken zihninizde sırayla işletebileceğiniz pratik bir kontrol listesi sunar:
- Veride tekrara izin var mı, yoksa her eleman tekil mi olmalı? Tekrara izin veriliyorsa List, tekil eleman gerekiyorsa Set ailesi tercih edilir.
- Sıralama gerekiyor mu; gerekiyorsa doğal sıralama mı yoksa ekleme sırası mı istenir? Doğal sıralama (alfabetik, sayısal) gerekiyorsa TreeSet veya TreeMap, ekleme sırası önemliyse LinkedHashSet veya LinkedHashMap, sıralama hiç önemli değilse HashSet veya HashMap seçilir.
- Veri bir anahtar-değer ilişkisi mi, yoksa tek başına duran elemanlar mı? Bir bilgiye başka bir bilgi üzerinden ulaşmak gerekiyorsa (örneğin kullanıcı adına göre profil bulmak) Map ailesi; sadece elemanların kendisiyle ilgileniliyorsa List veya Set yeterlidir.
- Arama ve erişim işlemi ne sıklıkla yapılacak? Arama işlemi az sayıda ve nadiren yapılıyorsa List'in basitliği yeterli olabilir; sık ve büyük hacimli arama yapılacaksa hash tabanlı yapılar (HashSet, HashMap) daha uygun bir zemin sunar.
- Veri sürekli baştan/ortadan mı ekleniyor, yoksa sona mı ekleniyor? Sık ortadan ekleme-çıkarma varsa LinkedList; sona ekleme ve indeksle erişim önemliyse ArrayList daha mantıklı bir seçimdir.
Bu beş soruyu sırayla cevapladığınızda, elinizde kalan seçenek sayısı genellikle bire iner. Bu karar mekanizmasını gerçek kod üzerinde, anlık geri bildirimle çalışarak içselleştirmek isteyen öğrenciler için birebir Java özel ders desteği, hangi senaryoda hangi yapının seçileceğini soyut kural olarak değil, yazdığınız projenin ihtiyacına göre öğrenmenizi sağlar. Kriterleri ezberlemek yerine her projede yeniden sormak, zamanla bu kararları saniyeler içinde ve doğru verme becerisi kazandırır.
Koleksiyon Seçimini Gerçek Projelerde Uygulamak
Teoriyi tek tek anlamak başka, bir problemin karşısına geçip "burada hangi koleksiyonu kullanmalıyım" sorusuna saniyeler içinde cevap verebilmek başka bir şeydir. Bunu somutlaştırmak için basit bir öğrenci kayıt sistemi tasarladığınızı düşünün. Sistemde üç farklı ihtiyaç ortaya çıkar ve her biri farklı bir koleksiyon ailesine işaret eder.
Öğrencilerin kayıt sırasına göre listelenmesi gerektiğinde, yani sıra önemliyse ve aynı öğrenci birden fazla kez görünebiliyorsa (örneğin bir dersi tekrar alıyorsa), List arayüzü devreye girer. Öğrenci numaralarının benzersiz olması gerektiği, aynı numaranın sisteme iki kez girilmesinin mantıksal bir hata sayılacağı yerde ise Set kullanılır; hangi Set'in seçileceği ise sıralamaya ihtiyaç olup olmamasına bağlıdır. Öğrenci numarasından öğrenci nesnesine hızlıca ulaşmak gerektiğinde — mesela "1234 numaralı öğrencinin bilgilerini getir" gibi bir sorguda — devreye Map girer; anahtar öğrenci numarası, değer ise öğrencinin kendisi olur.
Bu üç yapı aynı sistemde birbirini dışlamaz, birbirini tamamlar. Kayıt listesi bir ArrayList'te tutulurken, benzersizliği garanti edilmesi gereken numaralar bir HashSet'te kontrol edilebilir, hızlı arama gerektiren sorgular ise bir HashMap üzerinden yürütülebilir. Gerçek projelerin çoğunda tek bir koleksiyonla değil, birden fazla koleksiyonun birlikte çalıştığı bir mimariyle karşılaşırsınız; önemli olan her yapının hangi görevi en verimli şekilde üstlendiğini ayırt edebilmektir.
Bu ayırt etme becerisi ne yazık ki bir defa okuyup kazanılan bir bilgi değildir; tekrar tekrar farklı senaryolarla karşılaşıp doğru-yanlış deneyerek oturur. Bir öğrenci listesi projesini bugün ArrayList ile, yarın aynı projeyi LinkedHashSet ile yazıp performans farkını gözlemlemek, kitaptan okumaktan çok daha kalıcı bir öğrenme sağlar. Bu yüzden koleksiyon seçimi gibi konularda en büyük ilerleme, çok sayıda küçük problemle pratik yapıldığında görülür.
Berk Akademi'nin canlı Java derslerinde de bu yaklaşım benimsenir: koleksiyon seçimi gibi konular sadece anlatılmakla kalmaz, öğrencinin kendi kod yazma sürecinde defalarca karşısına çıkarılıp tartışılır. canlı Java dersleri kapsamında bu tür kararlar gerçek kod örnekleri üzerinden, eğitmen geri bildirimiyle birlikte işlenir; böylece öğrenci sadece "hangi koleksiyonun ne olduğunu" değil, "hangi durumda hangisini seçmesi gerektiğini" içselleştirir. Zamanla bu karar verme süreci bilinçli bir analiz olmaktan çıkıp neredeyse otomatik bir refleks haline gelir.
Sık Sorulan Sorular
ArrayList yerine ne zaman LinkedList kullanmalıyım?
Listenin başına veya ortasına sık sık ekleme ve silme yapıyorsanız, özellikle bu işlemleri bir iteratör üzerinden gerçekleştiriyorsanız LinkedList mantıklı bir seçenektir. Buna karşılık indeksle rastgele erişim ağırlıklıysa, yani "beşinci elemanı getir" gibi sorgular sık tekrarlanıyorsa ArrayList çok daha uygun çalışır.
HashSet'te neden aynı görünen elemanlar tekrar ekleniyor?
Bu durum genellikle nesnenin equals() ve hashCode() metotlarının doğru şekilde geçersiz kılınmamasından kaynaklanır. HashSet, bir elemanın zaten var olup olmadığını anlamak için önce hashCode() değerine, sonra equals() karşılaştırmasına bakar; bu iki metot varsayılan haliyle bırakılırsa nesneler görünüşte aynı olsa da farklı kabul edilip tekrar eklenebilir.
TreeMap her zaman HashMap'ten daha mı yavaştır?
Genel eğilim olarak evet, çünkü TreeMap her ekleme ve arama işleminde sıralamayı korumak için ek bir karşılaştırma maliyeti taşır, HashMap ise böyle bir yükümlülüğü olmadığı için genellikle daha hızlı çalışır. Ancak veriye zaten sıralı erişmeniz gerekiyorsa, TreeMap'in bu "maliyeti" aslında sonradan ayrı bir sıralama işlemi yapmaktan çok daha verimli bir çözüm sunar.
List, Set ve Map aynı projede birlikte kullanılabilir mi?
Kesinlikle kullanılabilir, hatta gerçek projelerin büyük bir kısmında birlikte kullanılırlar. Her yapı farklı bir soruna cevap verir; sıralı ve tekrarlı veri için List, benzersizlik gereksinimi için Set, anahtar-değer eşleşmesi için Map tercih edilir ve bu üçü genellikle aynı sistemin farklı katmanlarında bir arada bulunur.
Sıralı veriye ihtiyacım varsa her zaman TreeSet veya TreeMap mi seçmeliyim?
Hayır, çünkü "sıralı" ihtiyacının türü önemlidir. Eğer sadece ekleme sırasının korunması yeterliyse LinkedHashSet veya LinkedHashMap daha az maliyetle aynı işi görür; asıl doğal sıralama veya özel bir karşılaştırma kuralına göre sürekli sıralı kalması gereken veri için TreeSet ve TreeMap tercih edilmelidir.
Koleksiyon seçimini bir mülakatta nasıl hızlı ve doğru açıklarım?
En sağlam yaklaşım, önce veriye ihtiyaç duyulan işlemi tanımlamak, sonra o işlemin hangi koleksiyonda daha verimli çalıştığını mantığıyla açıklamaktır. "Tekrar var mı, sıra önemli mi, anahtar-değer eşleşmesi mi gerekiyor" sorularını sırayla cevaplayıp buna göre List, Set veya Map arasında seçim yaptığınızı göstermek, ezberlenmiş tanımlar sıralamaktan çok daha etkili bir izlenim bırakır.
List, Set ve Map arasındaki farkları anlamak, aslında veriyle ilgili doğru soruları sormayı öğrenmekle aynı şeydir; bir kez bu soruları sorma alışkanlığı kazandığınızda koleksiyon seçimi artık kararsızlık kaynağı olmaktan çıkar. Bu konuyu daha fazla alıştırmayla ve gerçek kod senaryolarıyla pekiştirmek isterseniz 1-1 özel Java dersleri sayfasını inceleyebilirsiniz.