İçeriğe geç

Comparable ve Comparator — Kim Önce Gelir?

Başlangıç 8 dk Çok sık karşılaşılır

Önce şunu oku: Lambda ve Fonksiyonel Arayüzler — Lambda Neyi Yakalar?

30 saniyede özet

Comparable bir sınıfın kendi doğal sırasını söyler, Comparator ise dışarıdan istediğin kadar farklı sıra tanımlar. Sıralarken iki kuralı zincirleyebilir, metinleri dile uygun sıralamak için Collator kullanırsın.

Bir kuyrukta insanları boylarına göre dizmek istediğini düşün. Önce “kim daha kısa?” sorusunun cevabını bilmen gerekir.

Java da bir listeyi sıralamadan önce aynı soruyu sorar: bu ikisinden hangisi önce gelir?

Önce tutara göre, tutar eşitse tarihe göre: iki kural, tek bir sıra.
Adım adım oku
  1. Dört hesap hareketi karışık sırada duruyor.
  2. Önce tutara göre sıralanıyorlar: 200'ler önde, 500'ler arkada.
  3. Tutarı eşit olanlar arasında tarihe bakılıyor: eski tarih önce.
  4. Sonuç: küçük tutar önce, eşitlikte eski tarih önce.
  1. Bayt: Hareketleri tutara göre sıraladım, ama eşit tutarlılar karmakarışık!

  2. Sen: Onlara hangi sırayla dizileceklerini söyledin mi?

  3. Bayt: Hayır... sadece tutara bak dedim. Eşitlikte ne yapacağını bilmiyor.

  4. Bayt: O zaman ona ikinci bir kural öğretelim. Hem de tek satırda.

Doğal sıra: Comparable

Bir sınıf Comparable uygularsa kendi doğal sıraBir sınıfın Comparable ile kendi içine yazdığı varsayılan sıralama. Sayılarda küçükten büyüğe, tarihlerde eskiden yeniye.Metinlerin doğal sırası harf kodlarına göredir; bu yüzden insanlara gösterilecek listelerde çoğu zaman ayrı bir Comparator ya da Collator gerekir.Sözlükte gör → tanımlar. compareTo metodu üç cevaptan birini verir: negatif (ben önce), sıfır (eşitiz), pozitif (sen önce).

Kendi sırasını bilen sınıf
record Tutar(long kurus) implements Comparable<Tutar> {
@Override
public int compareTo(Tutar diger) {
return Long.compare(this.kurus, diger.kurus);
}
}
Collections.sort(tutarlar); // doğal sıraya göre: küçükten büyüğe

String, Integer, LocalDate gibi birçok hazır tipin doğal sırası zaten vardır. Onları sıralamak için hiçbir şey yazmana gerek yok.

Kafam karıştı, daha basit anlat

compareTo iki şeyi yan yana koyup “hangisi önce” diye sorar. Eksi çıkarsa ben önce, artı çıkarsa sen önce, sıfır çıkarsa eşitiz.

Hızlı kontrolBaşlangıç

`a.compareTo(b)` negatif bir sayı döndürdü. Bu ne demek?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Başka bir sıra: Comparator

`List.of("banka", "Zeytin", "armut")` doğal sırasıyla sıralanırsa sonuç ne olur? Cevabı göster

[Zeytin, armut, banka]. String’in doğal sırası harflerin bilgisayardaki sayı karşılığına bakar ve büyük harfler küçük harflerden önce gelir.

Doğal sıra her zaman istediğin sıra değildir. Comparator, sınıfa dokunmadan dışarıdan yeni bir sıra tanımlar. Aynı liste için istediğin kadar Comparator yazabilirsin.

Dışarıdan sıra tanımlamak
list.sort(Comparator.comparing(Musteri::ad)); // ada göre
list.sort(Comparator.comparing(Musteri::ad).reversed()); // ters sıra
list.sort(String.CASE_INSENSITIVE_ORDER); // büyük/küçük harf farkı yok
Kafam karıştı, daha basit anlat

Comparable sınıfın kendi huyudur, bir tane olur. Comparator ise dışarıdan verilen bir talimattır: “bugün şuna göre diz”. İstediğin kadar talimat yazabilirsin.

Çağla neden Zeynep’ten sonra?

Tohum 26380

    Oynat ya da adımla: her adımda bir isim yerine oturur.

    Hız
    Adım 0

    Şu an ne oldu?

    Doğal sıra (compareTo)

    7 müşteri adı sıralanacak.

    Görevler0/3

    • Çağla’yı Zeynep’ten sonraya koyaçık

      İpucu

      Varsayılan ayarlar yeter.

    • ali başa geçsin ama Çağla hâlâ Zeynep’ten sonra kalsınaçık

      İpucu

      Harf büyüklüğünü yok say.

    • İsimleri Türk alfabesine göre sıralaaçık

      İpucu

      Dili bilen bir karşılaştırıcı.

    Olay günlüğü (0)

    Henüz olay yok. Oynat veya adımla.

    1. Varsayılanla oynat. Doğal sırada önce büyük harfler, sonra ali, en sonda Çağla, Ömer ve İlker geldi.
    2. “CASE_INSENSITIVE_ORDER” seç. ali başa geçti, ama Çağla ve Ömer hâlâ Zeynep’ten sonra.
    3. “Türk alfabesi” seç. Herkes alfabedeki yerine oturdu.
    Hızlı kontrolBaşlangıç

    Program ne yazdırır?

    Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.
    Sirala.java
    1List<String> meyveler = new ArrayList<>(List.of("banka", "Zeytin", "armut"));
    2Collections.sort(meyveler);
    3System.out.println(meyveler);
    Java 21UTF-8LF

    Musteri sınıfını değiştiremiyorsun ama müşterileri yaşa göre sıralaman gerekiyor. Ne yaparsın?

    Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

    Satır satır: eşitlikte ikinci kural

    Sahnedeki sıralamayı koda dökelim: önce tutar, tutar eşitse tarih.

    İki kurallı sıralama

    Ekstre.java
    1hareketler.sort(
    şu an çalışan satır Comparator.comparing(Hareket::tutar)
    3 .thenComparing(Hareket::tarih)
    4);

    Debug

    Adım 1/3

    1. kural İki hareketin tutarı karşılaştırılır. Farklıysa karar verilmiştir, ikinci kurala hiç bakılmaz.

    200 vs 500
    = 200 önce
    Java 21UTF-8LF2:1

    Sol/sağ ok tuşlarıyla da gezebilirsin.

    Hızlı kontrolBaşlangıç

    `Comparator.comparing(Hareket::tutar).thenComparing(Hareket::tarih)` iki hareketi karşılaştırırken tarihe ne zaman bakar?

    Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

    Sıra, eşitliği de belirler

    TreeSet ve TreeMap elemanları sıralı tutar. İki elemanın aynı olup olmadığına da equals ile değil, karşılaştırmanın sıfır dönüp dönmediğine bakarak karar verirler.

    Aynı yaş, aynı kişi mi?
    Set<Musteri> set = new TreeSet<>(Comparator.comparing(Musteri::yas));
    set.add(new Musteri("Ali", 30));
    set.add(new Musteri("Ayşe", 30)); // eklenmez: yaşlar eşit, "aynı" sayıldı

    Bu yüzden sıralı bir kümede Comparator’ı, gerçekten farklı olan iki elemanı ayırabilecek kadar ayrıntılı yazarsın.

    Kafam karıştı, daha basit anlat

    TreeSet’e göre “sıralamada eşit” demek “aynı kişi” demektir. Sadece yaşa bakarsan aynı yaştaki iki farklı kişiden biri kaybolur.

    Hızlı kontrolOrta

    Program ne yazdırır?

    Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.
    Kume.java
    1record Musteri(String ad, int yas) {}
    2
    3Set<Musteri> set = new TreeSet<>(Comparator.comparingInt(Musteri::yas));
    4set.add(new Musteri("Ali", 30));
    5set.add(new Musteri("Ayşe", 30));
    6set.add(new Musteri("Can", 25));
    7System.out.println(set.size());
    Java 21UTF-8LF

    Bankada bunun en tipik yeri ekstrelerdir. Hareketler tarihe göre dizilir, aynı saniyedeki hareketler de işlem numarasıyla ayrılır.

    Derinleş · Ekstre sıralaması ve Türkçe müşteri listesi 3 dosya · ~34 satır · ilk okumada atlayabilirsin
    Proje dosyaları

    src/main/java/com/bank/statement/ Movement.java Hareket: tutar ve tarih; doğal sırası tarih, eşitlikte işlem numarası.

    src/main/java/com/bank/statement/Movement.java
    public record Movement(long id, LocalDateTime at, BigDecimal amount) implements Comparable<Movement> {
    private static final Comparator<Movement> ORDER =
    Comparator.comparing(Movement::at).thenComparingLong(Movement::id);
    @Override
    public int compareTo(Movement other) {
    return ORDER.compare(this, other);
    }
    }

    src/main/java/com/bank/customer/ CustomerNames.java Müşteri adlarını Türkçe kurallarıyla sıralamak için Collator.

    src/main/java/com/bank/customer/CustomerNames.java
    public final class CustomerNames {
    private static final Collator TURKISH = Collator.getInstance(Locale.forLanguageTag("tr-TR"));
    private CustomerNames() {
    }
    public static List<String> sorted(List<String> names) {
    List<String> copy = new ArrayList<>(names);
    copy.sort(TURKISH);
    return copy;
    }
    }

    src/main/java/com/bank/ Main.java Çıktı yorumlarda.

    src/main/java/com/bank/Main.java
    public class Main {
    public static void main(String[] args) {
    List<String> names = List.of("Zeynep", "çağla", "Ayşe", "Ömer");
    System.out.println(names.stream().sorted().toList());
    // [Ayşe, Zeynep, Ömer, çağla] harf koduna göre: Türkçe harfler en sona
    System.out.println(CustomerNames.sorted(names));
    // [Ayşe, çağla, Ömer, Zeynep] Türkçe alfabe sırası
    }
    }

    Tuzaklar

    a - b ile karşılaştırmak. Çok büyük ve çok küçük iki sayının farkı taşar ve işareti ters çıkabilir. Integer.compare(a, b) ya da Comparator.comparingInt kullan.

    Türkçe adları doğal sırayla dizmek. Doğal sıra harf kodlarına bakar: Ç, Ö, Ş gibi harfler Z’den sonraya düşer. Türkçe sıra için CollatorMetinleri bir dilin alfabe kurallarına göre karşılaştıran Java sınıfı. Türkçe için ç harfini c ile d arasına koyar.Collator.getInstance(Locale.forLanguageTag("tr-TR")) bir Comparator gibi kullanılır: list.sort(collator).Sözlükte gör → kullan.

    Boş (null) değerler. Sıralanan alanlardan biri null olabiliyorsa Comparator.nullsLast(...) ile nereye gideceklerini açıkça söyle.

    Hızlı kontrolOrta

    Bu sıralama çoğu zaman doğru, ama çok büyük ve çok küçük tutarlar bir arada olunca sıra bozuluyor. Hatalı satır hangisi?

    Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

    Hatalı satıra dokun, sonra kontrol et.

    Siralama.java
    Java 21UTF-8LF

    Kendini sına

    Şimşek turu1/4

    Bir sınıfın birden çok Comparable sırası olabilir.

    Soru 1/3Başlangıç

    Comparable ile Comparator arasındaki temel fark nedir?

    Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

    Aklında kalacak üç şey

    1. 1 Comparable sınıfın içine yazılan tek bir doğal sıradır; Comparator ise dışarıdan, istediğin kadar farklı sıra tanımlar.
    2. 2 Comparator.comparing(...).thenComparing(...) önce bir kurala göre sıralar, eşitlik olursa ikinci kurala bakar.
    3. 3 İki sayıyı a - b ile değil Integer.compare(a, b) ile karşılaştırmak taşmayı önler; Türkçe metinleri doğru sıralamak için Collator gerekir.
    Sonraki kapı Kasa 0.10 ile 0.20'yi topladı ve 0.30 çıkmadı. Bilgisayar toplama yapmayı mı unuttu? BigDecimal — Parada Kuruş Kaybetmemek · 8 dk

    3 kart sonraki derste seni bekliyor

    0/3 kart bu dersten toplandı