CodeGym /Kurslar /JAVA 25 SELF /Set: HashSet və TreeSet, elementlərin unikallığı

Set: HashSet və TreeSet, elementlərin unikallığı

JAVA 25 SELF
Səviyyə , Dərs
Mövcuddur

1. Giriş

Gəlin həyati bir nümunə ilə başlayaq. Təsəvvür edin ki, siz bir məclis təşkil edirsiniz və qonaqların siyahısını tərtib edirsiniz. Dəvətnamələr göndərirsiniz, sonra isə məlum olur ki, eyni şəxs siyahıya iki dəfə (hətta üç dəfə — axı o, məclisləri çox sevir!) düşüb. Əgər adi bir siyahıdan (List) istifadə etsəniz, belə dublikatlar asanlıqla yarana bilər. Amma elə bir kolleksiyanız olsaydı ki, eyni qonağı ikinci dəfə əlavə etməyə imkan verməsin — həyat daha asan olardı.

Məhz burada Set kolleksiyası — çoxluq — işə düşür.

Set yalnız unikal elementləri saxlayan bir kolleksiyadır. Artıq mövcud olan element əlavə edilməyə çalışıldıqda, o sadəcə əlavə olunmur (və heç kim incimir).

Set interfeysi: əsas xüsusiyyətlər

Java-da Set — dublikatları olmayan kolleksiyanın davranışını müəyyən edən interfeysdir. O, Collection interfeysindən miras alır, yəni əlavə etmə (add), silmə (remove), elementin mövcudluğunu yoxlama (contains) və üzərindən keçmə kimi əməliyyatları dəstəkləyir.

Əsas xüsusiyyətlər:

  • Set-də iki eyni element ola bilməz.
  • Elementlər istənilən qaydada saxlanıla bilər — bu, konkret reallaşdırmadan asılıdır.
  • İndekslər yoxdur: siyahıdakı kimi nömrə ilə elementə müraciət etmək mümkün deyil.

Elan sintaksisi

Set<String> guests = new HashSet<>();

2. HashSet: sürətli, sadə, sırasız

HashSet — interfeys Set-in ən populyar reallaşdırmasıdır. O, hash-cədvələ əsaslanır (elə HashMap kimi, sadəcə «açar-dəyər» cütü olmadan, unikal dəyərlərlə). Əsas üstünlük — sürət: əlavəetmə, silmə və axtarış əməliyyatları çevikdir.

HashSet necə işləyir?

Bir qutu təsəvvür edin ki, ora əşyalarınızı yığırsınız. Nə isə oxşarın artıq olub-olmadığını tez başa düşmək üçün hər əşya öz «nömrəsini» — hash-kodu alır. Siz elementi HashSet-ə əlavə edəndə əvvəlcə həmin hash-kod hesablanır. Əgər belə bir kod hələ rast gəlinməyibsə, element sakitcə kolleksiyaya yerləşdirilir. Əgər həmin hash artıq varsa, əlavə olaraq equals() vasitəsilə bərabərlik yoxlanılır. Və yalnız obyektlər həqiqətən eyni olduqda, yeni element əlavə edilmir.

Deməli, HashSet unikallığa avtomatik nəzarət edir: iki eyni obyekt orada görünməyəcək.

Maraqlı məqam: əgər öz siniflərinizlə işləyirsinizsə və onları HashSet-də saxlamaq istəyirsinizsə, equals()hashCode() metodlarını yenidən müəyyən etməli olacaqsınız. Əks halda kolleksiya proqnozlaşdırılmayan şəkildə davrana bilər — guya eyni olan obyektlər fərqli sayılacaq.

HashSet-in əsas metodları

Set<String> guests = new HashSet<>();

guests.add("İvan");
guests.add("Mariya");
guests.add("Pyotr");
guests.add("İvan"); // Dublikat! Əlavə olunmayacaq.

System.out.println(guests); // [İvan, Mariya, Pyotr] — sıra istənilən ola bilər

guests.remove("Pyotr"); // Elementi silirik
System.out.println(guests.contains("Mariya")); // true
System.out.println(guests.size()); // 2

Gəlin bunu kodda yoxlayaq

Tutaq ki, tətbiqimizdə eyni adlı iki tapşırığın olmaması üçün unikal tapşırıq adlarını saxlamaq istəyirik:

import java.util.HashSet;
import java.util.Set;

public class UniqueTasksDemo {
    public static void main(String[] args) {
        Set<String> tasks = new HashSet<>();
        tasks.add("Java üzrə ev tapşırığını etmək");
        tasks.add("Pişiyi sığallamaq");
        tasks.add("Java üzrə ev tapşırığını etmək"); // Dublikat!

        System.out.println("Tapşırıqlar siyahısı:");
        for (String task : tasks) {
            System.out.println("- " + task);
        }
        // Siyahıda yalnız iki tapşırıq olacaq, dublikat əlavə olunmayacaq
    }
}

3. TreeSet: sıra vacibdir!

Bəzən bizə təkcə unikallıq deyil, həm də sıralanmış element toplusu lazımdır. Məsələn, qonaq adlarını əlifba üzrə görmək istərdik, təsadüfi qaydada deyil. Bunun üçün TreeSet var.

TreeSet — interfeys Set-in reallaşdırmasıdır, elementləri sıralanmış (artan) qaydada saxlayır. O, «qırmızı-qara ağac» strukturuna əsaslanır.

TreeSet istifadəsinə nümunə

import java.util.Set;
import java.util.TreeSet;

public class SortedGuestsDemo {
    public static void main(String[] args) {
        Set<String> guests = new TreeSet<>();
        guests.add("Vladimir");
        guests.add("Aleksey");
        guests.add("Yekaterina");
        guests.add("Aleksey"); // Dublikat!

        System.out.println("Qonaqlar (əlifba sırası ilə):");
        for (String guest : guests) {
            System.out.println("- " + guest);
        }
        // Çıxış:
        // - Aleksey
        // - Vladimir
        // - Yekaterina
    }
}

Nəzərə alın: Dublikat əlavə etsəniz, o çoxluqda görünməyəcək. Hər şey olduğu kimi işləyir!

TreeSet-i nə zaman istifadə etməli?

  • Sıralanmış unikal elementlər toplusu lazım olduqda.
  • Axtarışın sürəti vacib, lakin əlavə etmə sürəti kritik olmadıqda ( HashSet-dən bir qədər yavaşdır ).
  • Əgər elementlər — sizin öz siniflərinizdirsə, onlar «müqayisə oluna bilən» olmalıdır ( Comparable interfeysini reallaşdırmalıdır ) və ya siz öz Comparator-unuzu təqdim etməlisiniz.

4. Faydalı nüanslar

HashSet vs TreeSet: hansını seçməli?

Kriteriya HashSet TreeSet
Saxlanma qaydası Qarantiləşdirilmir Artan qaydada sıralanır
Əməliyyatların sürəti Daha sürətli (O(1)) Daha yavaş (O(log n))
Tip tələbləri İstənilən ( equals()/hashCode() kifayətdir ) Comparable və ya Comparator
Tipik ssenarilər Unikal elementlərə sürətli giriş lazım olduqda Nizamlı çıxış/keçid vacib olduqda

Set ilə işin xüsusiyyətləri

  • İndekslər yoxdur. List-dən fərqli olaraq, Set-də get(int index) metodu yoxdur. İndeks üzrə giriş lazımdırsa — List istifadə edin.
  • Dublikat yoxdur. Artıq mövcud olan elementi əlavə etməyə çalışsanız, o əlavə olunmayacaq. add metodu false qaytaracaq.
  • Sıra qarantiləşdirilmir (TreeSet istisna olmaqla). HashSet-də elementlərin sırası hər icrada fərqli ola bilər. Əlavəetmə sırası lazımdırsa, LinkedHashSet istifadə edin.
  • Null dəyərlər.
    • HashSet bir ədəd null element saxlamağa imkan verir.
    • TreeSet xüsusi Comparator olmadan null əlavə etməyə imkan vermir, əks halda NullPointerException olacaq.

5. Set üçün tipik vəzifələr

Siyahıdan dublikatların silinməsi

Tutaq ki, bizdə bəziləri iki dəfə yazılmış tələbə siyahısı var. Yalnız unikal adları saxlamaq lazımdır:

import java.util.*;

public class RemoveDuplicatesDemo {
    public static void main(String[] args) {
        List<String> students = Arrays.asList("Anna", "İqor", "Anna", "Mariya", "İqor", "Pavel");

        Set<String> uniqueStudents = new HashSet<>(students);

        System.out.println("Unikal tələbələr: " + uniqueStudents);
        // Sıra qarantiləşdirilmir!
    }
}

Əgər sıralanmış nəticə lazımdırsa — TreeSet istifadə edin:

Set<String> sortedUniqueStudents = new TreeSet<>(students);
System.out.println("Unikal tələbələr (əlifba sırası ilə): " + sortedUniqueStudents);

Unikallığın yoxlanması (məsələn, istifadəçi logininin)

Set<String> usedLogins = new HashSet<>();
usedLogins.add("student1");
usedLogins.add("java_lover");

String newLogin = "student1";
if (usedLogins.contains(newLogin)) {
    System.out.println("Bu login artıq istifadə olunur!");
} else {
    System.out.println("Login boşdur!");
}

Çoxluğun elementləri üzərindən keçmək

Üzərindən keçmək for-each dövrü ilə aparılır:

for (String name : uniqueStudents) {
    System.out.println(name);
}

6. Set ilə işləyərkən tipik səhvlər

Səhv №1: HashSet-də elementlərin müəyyən bir sırasını gözləmək. Bir çox yeni başlayanlar çoxluq elementlərinin « qəribə » sırada çıxmasına təəccüblənir. Bu normaldır — HashSet sıra qarantiləşdirmir. Əlavəetmə sırası lazımdırsa — LinkedHashSet, sıralama lazımdırsa — TreeSet.

Səhv №2: Elementə indeks üzrə müraciət etməyə cəhd. Bəzən set.get(0) kimi bir şey yazmağa çalışırlar. Belə olmaz: Set indeksləşdirməni dəstəkləmir. İndeks üzrə giriş lazımdırsa — List seçin.

Səhv №3: Dəyişən obyektləri saxlamaq. Əgər equals()/hashCode()-da iştirak edən sahələri dəyişə bilən obyektləri saxlayırsınızsa, həmin sahələr dəyişdikdən sonra element çoxluq üçün «itirilə» bilər. Elementləri dəyişməz edin və ya identifikasiyaedici sahələri dəyişməyin.

Səhv №4: Dublikatların əlavə olunacağını gözləmək. Eyni elementi bir neçə dəfə əlavə etmək çoxluğun ölçüsünü artırmayacaq — dublikatlar yox sayılır, add metodu false qaytaracaq.

Səhv №5: Primitiv tiplərdən istifadə. Set<int> kimi yazılış kompilyasiya olunmayacaq. Wrapper siniflərdən istifadə edin: Set<Integer>, Set<Double> və s.

1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Tədbir iştirakçılarının əlifba sırası üzrə siyahısı 🤵‍♀️🤵‍♂️
Tədbir iştirakçılarının əlifba sırası üzrə siyahısı 🤵‍♀️🤵‍♂️
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Alış-veriş siyahısının optimallaşdırılması 🛒✨
Alış-veriş siyahısının optimallaşdırılması 🛒✨
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION