Üniversitede bir gün, sınıf arkadaşlarımın kişisel verilerinin anahtarı olan soyadlarını artan düzende sıralamak için bir kod yazmam gerekiyordu. Bunun için çok zaman harcadım. Ama o zamanlar TreeMap sınıfını bilseydim , görevi çok daha hızlı bitirirdim.

Ağaç Haritası nedir ? Öğeleri anahtar-değer çiftleri olarak depolayan ve bunları anahtara göre sıralayan sözlük benzeri bir veri yapısıdır.

Nerede ve nasıl kullanılabilir? Sınıf arkadaşlarımın soyadlarıyla aynı ödev için ideal olurdu. Değerleri artan sırada depolamam gerekirse, kendi sıralama algoritmamı yazmak yerine tek yapmam gereken bir TreeMap oluşturmak ve değerleri içine koymak.

Integer ve String gibi türleri artan düzende sıralar . Ancak kendi özel türünüzü bir TreeMap içine koymak istiyorsanız , o zaman sınıfınızın, sınıfınızın örneklerinin nasıl sıralanacağını gösteren CompareTo() yöntemini uygulaması için Comparable arabirimini uygulaması gerekir.


public class Person implements Comparable<Person> {
 
    private String firstName;
    private String lastName;
 
    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
 
    public String getFirstName() {
        return firstName;
    }
 
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
 
  …
 
    @Override
    public int compareTo(Person person) {
        return person.getFirstName().compareTo(firstName);
    }
 
    @Override
    public String toString() {
        return "Person{" +
                "firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                '}';
    }
}

Değerleri ilk ada göre ters alfabetik sırada sıralayacak şekilde CompareTo() yöntemini geçersiz kılalım :


TreeMap map = new TreeMap<Person, String>();
 
map.put(new Person("AA","BB"), "aa");
map.put(new Person("BB","BB"), "aa");
map.put(new Person("DD","BB"), "aa");
map.put(new Person("CC","BB"), "aa");

Değerler aşağıdaki sırada saklanacaktır:


Person{firstName='DD', lastName='BB'}
Person{firstName='CC', lastName='BB'}
Person{firstName='BB', lastName='BB'}
Person{firstName='AA', lastName='BB'}

TreeMap sınıfı , SortedMap arabirimini genişleten NavigableMap arabirimini uygular . Bu, TreeMap sınıfının, değerleri sıralanmış düzende depolamak için ağaçları kullanmasına izin verir.

Wikipedia'nın dediği gibi, bir ağaç, değerleri ilk karşılaştırdıktan sonra verileri düğümlerinde depolayan, kendi kendini dengeleyen ikili bir arama yapısıdır.

Basit bir ifadeyle, kırmızı-siyah ağaç, değerleri kökten büyükse sağ alt ağaçta, küçükse sol alt ağaçta depolayan bir veri yapısıdır. Bu uygulama, yapıdaki değerleri çok hızlı bir şekilde arayabilir.

Kırmızı-siyah ağaç kendi kendini dengeler, bu nedenle eklenen her yeni değerde yapısını değiştirir. İlk eklenen değer başlangıçta kök olarak kabul edilir, ancak dengeleme işlemi sırasında başka bir değer kök olabilir.

Artık TreeMap'in ne olduğunu ve nasıl çalıştığını biliyorsunuz.

TreeMap'in yalnızca sınıfı Comparable arabirimini uygulayan ve CompareTo() yöntemini geçersiz kılan nesneleri depolayabildiğini unutmayın .

Ancak, çeşitli kitaplıklardan yüklenen üçüncü taraf sınıfları kullanıyorsak ve bunlarda Comparable'ı uygulayamazsak ne olur? Bunun için bir çözüm var: kendi Karşılaştırıcınızı yazın .

Comparator , Compare() yöntemine sahip bir arabirimdir. Nesneleri karşılaştırmak ve onları bir TreeMap'te saklamak için kullanabiliriz.


Comparator<Person> comparator = new Comparator<Person>() {
 
    @Override
    public int compare(Person person1, Person person2) {
        return person1.getFirstName().compareTo(person2.getFirstName());
    }
};
 
 
TreeMap map = new TreeMap<Person, String>(comparator);

Bu örnekte, özel bir Karşılaştırıcı oluşturduk ve sınıfa bir TreeMap geçirdik.

Java 8'den başlayarak, bunu bir lambda ifadesi kullanarak yazabiliriz:


TreeMap map = new TreeMap<Person, String>((Person person1, Person person2) -> person1.getFirstName().compareTo(person2.getFirstName()));

Başka bir deyişle, değerleri bir TreeMap içinde depolamak için bunların nasıl sıralanacağını belirtmeniz gerekir. Bunu yapmanın iki yolu vardır: Comparable'ı uygulayın veya kendi Comparator'ınızı uygulayın .

Peki ya bir TreeMap'e anahtar olarak null koymamız gerekirse ? HashMap bunu yapmanızı sağlar. Evet, ancak TreeMap bunu nasıl hallediyor?


TreeMap map = new TreeMap<Person, String>();
map.put (null, "Person");

Bu kodu çalıştırmak bize bir hata veriyor:

Java.base/java.util.TreeMap.put(TreeMap.java:561) adresindeki "main" java.lang.NullPointerException iş parçacığında istisna

Sorun, dahili olarak TreeMap sınıfının CompareTo() yöntemini kullanarak değerleri karşılaştırmasıdır . Kesinlikle boş bir değer iletebilirsiniz ve kod derlenir. Ancak çalışma zamanında bir hata alırsınız, çünkü yöntem boş bir değerde çağrılacak ve bir NullPointerException atılmasına neden olacaktır.

HashMap ve TreeMap'in Karşılaştırılması

TreeMap'ten farklı olarak HashMap , boş değeri bir anahtar olarak saklamanıza izin verir . Yapı, tüm boş anahtarlar için belirli bir yere sahiptir. HashMap boş anahtarları saklayabilir , çünkü bunların hash değerlerine göre nereye gittiklerini belirler ve hash değerini hesaplamak karşılaştırma gerektirmez. Böylece tüm boş anahtarların yerleri vardır.

İşte bu kadar - artık değerleri sıralanmış düzende saklamanız gerektiğinde ne kullanacağınızı ve sıralama kurallarını nasıl belirleyeceğinizi biliyorsunuz.