Comparable Arayüzü (Doğal Sıralama)
Nesneleri sıralamak istediğimizde, Java'nın "hangisi önce gelir?" sorusunu yanıtlaması gerekir. Sayılar için bu açıktır (küçükten büyüğe), String için alfabetiktir. Peki kendi sınıfların — Urun, Kisi? İşte burada Comp…
Comparable Arayüzü (Doğal Sıralama)
Nesneleri sıralamak istediğimizde, Java'nın "hangisi önce gelir?" sorusunu yanıtlaması gerekir.
Sayılar için bu açıktır (küçükten büyüğe), String için alfabetiktir. Peki kendi sınıfların —
Urun, Kisi? İşte burada Comparable devreye girer: bir sınıfa doğal sıra (natural
ordering) kazandırır, yani "bu tipin varsayılan sıralaması şudur" der.
compareTo: tek metot
Comparable<T> tek metot ister: int compareTo(T o). Dönüş değerinin işareti önemlidir:
- negatif → bu nesne,
o'dan önce gelir (this < o) - sıfır → eşit sıradalar
- pozitif → bu nesne,
o'dan sonra gelir (this > o)
class Urun implements Comparable<Urun> { private double fiyat; public int compareTo(Urun o) { return Double.compare(this.fiyat, o.fiyat); // doğal sıra: fiyat artan } }
İpucu: Karşılaştırmayı elle
this.x - o.xile yapma (taşma/NaNriski). Bunun yerineInteger.compare,Double.compare,String.compareTogibi hazır metotları kullan.
Doğal sırayı kim kullanır?
Comparable uygulayan bir tip, Java'nın tüm sıralama altyapısıyla otomatik çalışır:
Collections.sort(list)velist.sort(null)Arrays.sort(dizi)TreeSetveTreeMap(elemanları sıralı tutarlar)Collections.min/max, sıralı stream işlemleri
Örnek 1 (./Ornek1.java) fiyata göre doğal sıralı bir Urun tanımlar; sort, TreeSet.first()/ last() ile en ucuz/en pahalıyı bulur.
Çok alanlı sıralama
Genelde tek alan yetmez: önce soyada, eşitse ada, o da eşitse yaşa göre sırala. Bunu compareTo
içinde zincirleme yaparsın — ilk sıfır-olmayan sonuç kazanır:
public int compareTo(Kisi o) { int s = soyad.compareTo(o.soyad); if (s != 0) return s; int a = ad.compareTo(o.ad); if (a != 0) return a; return Integer.compare(yas, o.yas); }
Örnek 2 (./Ornek2.java) üç alana göre sıralar.
Sözleşme (contract) — ihlal etme!
compareTo belirli kurallara uymalıdır, yoksa sıralama ve TreeSet/TreeMap bozulur:
- Anti-simetri:
a.compareTo(b)ileb.compareTo(a)ters işaretli olmalı. - Geçişlilik:
a<bveb<cisea<c. - equals ile uyum (önerilir):
compareTo == 0olduğundaequals == trueolmalı. ÇünküTreeSet/TreeMapeşitliğiequalsile değilcompareToile belirler; uyumsuzluk "kümede var ama bulunamıyor" gibi sürprizlere yol açar. Bu yüzden Örnek 2'deequals/hashCode,compareToile aynı alanları kullanır.
Comparable mı, Comparator mı?
Comparable: Tipin tek, varsayılan sırası. Sınıfın içine yazılır (compareTo). "Bu tipin doğal sırası budur."Comparator: Dışarıdan, çok sayıda alternatif sıra. Sınıfı değiştirmeden farklı ölçütlerle sıralamak için (bir sonraki konu). Örn. ürünleri kâh fiyata kâh ada göre sıralamak.
İkisi birlikte kullanılır: doğal sıra Comparable ile, özel/çoklu sıralar Comparator ile.
Özet
Comparable ile bir tipe doğal sıra kazandırmayı: compareTo'nun işaret kuralını, hazır
compare metotlarını, doğal sırayı kullanan altyapıyı (sort, TreeSet) (Örnek 1); çok alanlı
zincirleme karşılaştırmayı ve equals ile uyum sözleşmesini (Örnek 2) öğrendik. Sırada, sınıfı
değiştirmeden esnek ve çoklu sıralama: Comparator.
▶ Kod Örnekleri(2)
Ornek1
çalıştırılabilir1// Ornek1: Comparable — bir nesneye "doğal sıra" (natural ordering) kazandırmak.
2// Çalıştırma: java Ornek1.java
3import java.util.ArrayList;
4import java.util.Collections;
5import java.util.List;
6import java.util.TreeSet;
7
8public class Ornek1 {
9
10 public static void main(String[] args) {
11 List<Urun> urunler = new ArrayList<>(List.of(
12 new Urun("Monitör", 3200), new Urun("Mouse", 250),
13 new Urun("Klavye", 450), new Urun("Kulaklık", 900)));
14
15 // Urun, Comparable uyguladığı için doğrudan sıralanabilir (doğal sıra: fiyata göre).
16 Collections.sort(urunler);
17 System.out.println("Doğal sıra (fiyat artan):");
18 urunler.forEach(u -> System.out.println(" " + u));
19
20 // list.sort(null) da doğal sırayı kullanır:
21 urunler.sort(null);
22
23 // TreeSet doğal sırayı kullanarak elemanları SIRALI tutar (Comparable şart).
24 TreeSet<Urun> sirali = new TreeSet<>(urunler);
25 System.out.println("\nTreeSet (en ucuz): " + sirali.first());
26 System.out.println("TreeSet (en pahalı): " + sirali.last());
27
28 System.out.println("""
29
30 --- Comparable (doğal sıra) ---
31 Comparable<T> uygulayan sınıf 'doğal' bir sıraya sahip olur: compareTo(o) metodu.
32 Dönüş: negatif (bu < o), 0 (eşit), pozitif (bu > o).
33 Collections.sort, list.sort(null), TreeSet, TreeMap, Arrays.sort bunu kullanır.
34 Tek bir 'varsayılan' sıralama için idealdir (ör. sayılar artan, String alfabetik).""");
35 }
36}
37
38// Comparable: bu sınıfın nesneleri kendi aralarında karşılaştırılabilir.
39class Urun implements Comparable<Urun> {
40 private final String ad;
41 private final double fiyat;
42 Urun(String ad, double fiyat) { this.ad = ad; this.fiyat = fiyat; }
43
44 @Override
45 public int compareTo(Urun diger) {
46 // Doğal sıra = fiyata göre artan. (Double.compare taşma/NaN güvenli.)
47 return Double.compare(this.fiyat, diger.fiyat);
48 }
49
50 @Override public String toString() { return ad + " (" + fiyat + " TL)"; }
51}Ornek2
çalıştırılabilir1// Ornek2: Çok alanlı compareTo ve equals ile tutarlılık.
2// Çalıştırma: java Ornek2.java
3import java.util.ArrayList;
4import java.util.List;
5import java.util.Objects;
6
7public class Ornek2 {
8
9 public static void main(String[] args) {
10 List<Kisi> kisiler = new ArrayList<>(List.of(
11 new Kisi("Yılmaz", "Ada", 30),
12 new Kisi("Yılmaz", "Burak", 25),
13 new Kisi("Demir", "Ada", 40),
14 new Kisi("Demir", "Ada", 22)));
15
16 kisiler.sort(null); // doğal sıra: soyad -> ad -> yaş
17 System.out.println("Çok alanlı doğal sıra (soyad, ad, yaş):");
18 kisiler.forEach(k -> System.out.println(" " + k));
19
20 System.out.println("""
21
22 --- Çok alanlı compareTo ve sözleşme ---
23 Birden çok ölçüte göre sıralamak için compareTo'da ZİNCİRLEME karşılaştırma yap:
24 önce soyad; eşitse ad; o da eşitse yaş. İlk sıfır-olmayan sonuç kazanır.
25 Sözleşme kuralları:
26 - işaret tutarlı (a<b ise b>a), geçişli (a<b, b<c => a<c),
27 - mümkünse equals ile UYUMLU: compareTo==0 oldugunda equals==true olmalı
28 (TreeSet/TreeMap eşitliği compareTo ile belirler; uyumsuzluk sürprizlere yol açar).""");
29 }
30}
31
32class Kisi implements Comparable<Kisi> {
33 private final String soyad, ad;
34 private final int yas;
35 Kisi(String soyad, String ad, int yas) { this.soyad = soyad; this.ad = ad; this.yas = yas; }
36
37 @Override
38 public int compareTo(Kisi o) {
39 int s = this.soyad.compareTo(o.soyad); // 1) soyada göre
40 if (s != 0) return s;
41 int a = this.ad.compareTo(o.ad); // 2) eşitse ada göre
42 if (a != 0) return a;
43 return Integer.compare(this.yas, o.yas); // 3) o da eşitse yaşa göre
44 }
45
46 // compareTo ile UYUMLU equals/hashCode (aynı üç alan).
47 @Override public boolean equals(Object o) {
48 return o instanceof Kisi k && yas == k.yas
49 && soyad.equals(k.soyad) && ad.equals(k.ad);
50 }
51 @Override public int hashCode() { return Objects.hash(soyad, ad, yas); }
52 @Override public String toString() { return soyad + " " + ad + " (" + yas + ")"; }
53}