İçeriğe geç
Educora
İleri18 dk11 / 18

Koleksiyonlar ve generic'ler

Esnek veri yapılarını — ArrayList, HashMap ve HashSet — kullan ve generic'lerin tür güvenliğini nasıl sağladığını öğren.

Kendini test et
Bu derste öğreneceklerin
  • ArrayList ile eleman eklemek, silmek, değiştirmek ve sıralamak
  • Anahtar–değer çiftlerini HashMap'te, benzersiz değerleri HashSet'te saklamak
  • List<String> gibi generic türleri okumak ve basit bir generic sınıf yazmak

Bir dizinin uzunluğu sabittir: 5 yerlik bir diziye 6. elemanı ekleyemezsin. Oysa bir alışveriş sepeti, sohbet mesajları ya da oyuncu listesi sürekli büyür ve küçülür. Bunun için Java'da hazır koleksiyonlar vardır: java.util paketindeki esnek veri yapıları.

ArrayList: büyüyen liste

ArrayList, bir dizi gibi indekslerle çalışır ama eleman eklendikçe kendiliğinden büyür. Açılı parantezlerdeki <String>, listenin hangi türde elemanlar tuttuğunu belirtir. Değişken genellikle genel List arayüzü türünde tanımlanır; sağ tarafta ise türü tekrarlamamak için boş <> (“elmas”) yazılır.

Java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> cities = new ArrayList<>();
        cities.add("Baku");
        cities.add("Ganja");
        cities.add("Lankaran");
        cities.add(1, "Shaki");
        System.out.println(cities + " size=" + cities.size());
        System.out.println(cities.get(0) + ", " + cities.contains("Ganja"));
        cities.remove("Lankaran");
        cities.set(0, "Sumgait");
        Collections.sort(cities);
        System.out.println(cities);
        for (String c : cities) {
            System.out.print(c.toUpperCase() + " ");
        }
        System.out.println();
    }
}
Beklenen çıktı
[Baku, Shaki, Ganja, Lankaran] size=4
Baku, true
[Ganja, Shaki, Sumgait]
GANJA SHAKI SUMGAIT 
MetotNe yapar
add(x), add(i, x)sona ya da i konumuna ekler
get(i), set(i, x)i indeksindeki elemanı okur ya da değiştirir
remove(i), remove(x)indekse ya da değere göre siler
size(), isEmpty()eleman sayısı, liste boş mu
contains(x), indexOf(x)eleman var mı, nerede
Etkileşimli
Simülasyon yükleniyor…
list.contains(x) elemanları tek tek kontrol eder; tıpkı bu doğrusal arama gibi. Liste büyüdükçe arama da uzar. Sık sık “bu eleman var mı?” diye soruyorsan aşağıdaki HashSet çok daha hızlıdır.

HashMap: anahtarlar ve değerler

Bir eşlem (Map), her anahtarı bir değerle ilişkilendirir; tıpkı bir sözlük gibi: kelime → anlam, ülke → başkent. Anahtarlar benzersizdir: aynı anahtarla yeniden put yaparsan eski değer değiştirilir. get, anahtar bulunamazsa null, getOrDefault ise senin verdiğin yedek değeri döndürür.

Java
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class Main {
    public static void main(String[] args) {
        Map<String, String> capitals = new HashMap<>();
        capitals.put("Azerbaijan", "Baku");
        capitals.put("Turkiye", "Ankara");
        capitals.put("Georgia", "Tbilisi");
        System.out.println(capitals.get("Turkiye"));
        System.out.println(capitals.get("France"));
        System.out.println(capitals.getOrDefault("France", "unknown"));
        System.out.println(capitals.containsKey("Georgia") + " " + capitals.size());

        String text = "to be or not to be";
        Map<String, Integer> counts = new TreeMap<>();
        for (String word : text.split(" ")) {
            counts.put(word, counts.getOrDefault(word, 0) + 1);
        }
        System.out.println(counts);
        for (Map.Entry<String, Integer> e : counts.entrySet()) {
            System.out.println(e.getKey() + " -> " + e.getValue());
        }
    }
}
Beklenen çıktı
Ankara
null
unknown
true 3
{be=2, not=1, or=1, to=2}
be -> 2
not -> 1
or -> 1
to -> 2

İkinci kısımda kelimeleri sayıyoruz: split(" ") metni kelimelere böler ve her kelimenin sayacı 1 artar. Burada bir TreeMap kullandık; o da bir Map'tir ama anahtarları alfabetik sırada tutar. HashMap ise öğeleri belirli bir sıra olmadan saklar: daha hızlıdır ama yazdırma sırası önceden bilinemez. entrySet() tüm anahtar–değer çiftlerini döngüyle gezmeyi sağlar.

HashSet: benzersiz elemanlar

Bir küme (Set) her elemanı yalnızca bir kez tutar. add, eleman eklendiyse true, zaten varsa false döndürür. HashSet'te contains bir listedekinden çok daha hızlıdır, çünkü elemanları tek tek kontrol etmez; bir karma kodu (hash code) kullanarak doğrudan doğru yere bakar.

Java
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

public class Main {
    public static void main(String[] args) {
        List<String> visitors = List.of("Leyla", "Murad", "Leyla", "Aysel", "Murad");
        Set<String> unique = new HashSet<>(visitors);
        System.out.println(visitors.size() + " visits, " + unique.size() + " people");
        System.out.println(unique.add("Elvin") + " " + unique.add("Leyla"));
        System.out.println(unique.contains("Aysel"));
        System.out.println(new TreeSet<>(unique));
    }
}
Beklenen çıktı
5 visits, 3 people
true false
true
[Aysel, Elvin, Leyla, Murad]

Generic'ler

List<String> ve Map<String, Integer> generic (genelleştirilmiş) türlerdir. Bunlar sayesinde derleyici listeye yanlış türde bir eleman koymana izin vermez ve elemanı alırken tür dönüşümü gerekmez. Koleksiyonlar yalnızca nesne tutar; bu yüzden ilkel türler yerine sarmalayıcı sınıflar yazılır: Integer, Double, Boolean, Character. Java, int ↔ Integer dönüşümünü otomatik yapar (autoboxing).

Java
import java.util.ArrayList;
import java.util.List;

public class Main {
    static <T> T last(List<T> list) {
        return list.get(list.size() - 1);
    }

    public static void main(String[] args) {
        Pair<String, Integer> p = new Pair<>("Aysel", 95);
        System.out.println(p.first() + " scored " + p.second());
        List<Integer> nums = new ArrayList<>(List.of(10, 20, 30));
        int total = 0;
        for (int n : nums) {
            total += n;
        }
        System.out.println(total + " " + last(nums) + " " + last(List.of("a", "b")));
        nums.remove(1);
        System.out.println(nums);
        nums.remove(Integer.valueOf(10));
        System.out.println(nums);
    }
}

class Pair<A, B> {
    private final A first;
    private final B second;

    Pair(A first, B second) {
        this.first = first;
        this.second = second;
    }

    A first() { return first; }
    B second() { return second; }
}
Beklenen çıktı
Aysel scored 95
60 30 b
[10, 30]
[30]
  • class Pair<A, B> bir generic sınıftır: A ve B tür parametreleridir; nesne oluşturulurken somut türlerle değiştirilir.
  • static <T> T last(List<T> list) bir generic metottur: aynı kod hem Integer hem de String listesi için çalışır.
  • List.of(...) tek satırda değiştirilemez bir liste oluşturur; değiştirmen gerekiyorsa new ArrayList<>(List.of(...)) yaz.

Önemli noktalar

  • ArrayList boyutu değişebilen bir listedir: add, get, set, remove, size.
  • HashMap anahtarları değerlerle eşler; anahtarlar benzersizdir, get anahtar yoksa null döndürür.
  • HashSet yalnızca benzersiz elemanları tutar ve contains kontrolünü çok hızlı yapar.
  • HashMap ve HashSet sıra tutmaz; sıralı sürümleri TreeMap ve TreeSet'tir.
  • Generic'ler (List<String>) tür güvenliği sağlar; ilkel türler yerine Integer, Double gibi sarmalayıcı sınıflar kullanılır.

Kendini test et

10 soru. Her doğru cevap XP kazandırır.

1 / 10
ArrayList gibi bir koleksiyon diziden nasıl ayrılır?