Comparable ve Comparator — Kim Önce Gelir?
Ö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?
Adım adım oku
- Dört hesap hareketi karışık sırada duruyor.
- Önce tutara göre sıralanıyorlar: 200'ler önde, 500'ler arkada.
- Tutarı eşit olanlar arasında tarihe bakılıyor: eski tarih önce.
- Sonuç: küçük tutar önce, eşitlikte eski tarih önce.
-
Bayt: Hareketleri tutara göre sıraladım, ama eşit tutarlılar karmakarışık!
-
Sen: Onlara hangi sırayla dizileceklerini söyledin mi?
-
Bayt: Hayır... sadece tutara bak dedim. Eşitlikte ne yapacağını bilmiyor.
-
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).
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üğeString, 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.
`a.compareTo(b)` negatif bir sayı döndürdü. Bu ne demek?
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.
list.sort(Comparator.comparing(Musteri::ad)); // ada görelist.sort(Comparator.comparing(Musteri::ad).reversed()); // ters sıralist.sort(String.CASE_INSENSITIVE_ORDER); // büyük/küçük harf farkı yokKafam 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 26380Oynat ya da adımla: her adımda bir isim yerine oturur.
Ş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.
- Varsayılanla oynat. Doğal sırada önce büyük harfler, sonra
ali, en sonda Çağla, Ömer ve İlker geldi. - “CASE_INSENSITIVE_ORDER” seç.
alibaşa geçti, ama Çağla ve Ömer hâlâ Zeynep’ten sonra. - “Türk alfabesi” seç. Herkes alfabedeki yerine oturdu.
Program ne yazdırır?
Musteri sınıfını değiştiremiyorsun ama müşterileri yaşa göre sıralaman gerekiyor. Ne yaparsın?
Satır satır: eşitlikte ikinci kural
Sahnedeki sıralamayı koda dökelim: önce tutar, tutar eşitse tarih.
İki kurallı sıralama
hareketler.sort( Comparator.comparing(Hareket::tutar) .thenComparing(Hareket::tarih));Debug
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
Sol/sağ ok tuşlarıyla da gezebilirsin.
`Comparator.comparing(Hareket::tutar).thenComparing(Hareket::tarih)` iki hareketi karşılaştırırken tarihe ne zaman bakar?
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.
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.
Program ne yazdırır?
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
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.
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?
Kendini sına
Bir sınıfın birden çok Comparable sırası olabilir.
Comparable ile Comparator arasındaki temel fark nedir?
Aklında kalacak üç şey
- 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 Comparator.comparing(...).thenComparing(...) önce bir kurala göre sıralar, eşitlik olursa ikinci kurala bakar.
- 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.
3 kart sonraki derste seni bekliyor