1. Klassik kolleksiyalarda sıra problemi
Java-da həmişə elementlərin ardıcıllığını təmin edən kolleksiyalar (məsələn, ArrayList, LinkedList, LinkedHashSet, LinkedHashMap) və ardıcıllıq təmin etməyənlər (məsələn, HashSet, HashMap) mövcud olub. Lakin bu kolleksiyaların hamısının bir ümumi çatışmazlığı var idi: bəziləri elementləri müəyyən qaydada saxlasalar da, standart interfeyslər (List, Set, Map) birinci və sonuncu elementlərə çıxış üçün və ya ardıcıllığı tərsinə çevirmək üçün universal metodlar təqdim etmirdi.
Məsələn, əgər sizdə List<String> varsa, birinci elementi list.get(0) ilə götürə bilərsiniz, lakin Set və ya Map üçün bu fənd işləməyəcək — ya iteratorlardan istifadə etməli, ya da əlavə kod yazmalı olacaqsınız. Razılaşın, bu nə çox rahatdır, nə də oxunaqlılığı artırır.
Bu elədir ki, sanki sizdə siyirtməli bir şkaf var, amma hər dəfə birinci və ya sonuncu siyirtməni çıxarmaq üçün bütün siyirtmələri əl ilə saymalı olursunuz! “Birinci” və “sonuncu” üçün xüsusi dəstəklər olsaydı, əla olmazdımı?
SequencedCollection və əlaqəli interfeyslərin yaradılması
Java 21-də yeni kolleksiya interfeysləri təqdim edildi:
- SequencedCollection<E>
- SequencedSet<E>
- SequencedMap<K, V>
Bu interfeyslər standart kolleksiyaları genişləndirir və elementlərin ardıcıllığı ilə işləməyə vahid yanaşma gətirir. İndi ardıcıllığın vacib olduğu hər hansı kolleksiyalar üçün, konkret reallaşdırma haqqında düşünmədən universal kod yaza bilərsiniz.
Bu nədir?
- SequencedCollection — elementlərin müəyyən qaydada olduğu və birinci, sonuncu elementi asanlıqla əldə etmək, həmçinin ardıcıllığı tərsinə çevirmək imkanı olan kolleksiyadır.
- SequencedSet — eyni yanaşma, lakin çoxluqlar (unikal elementlər) üçün.
- SequencedMap — eyni yanaşma, lakin xəritələr (açar-dəyər) üçün.
İndi bunları hansı kolleksiyalar reallaşdırır?
Java 21-də yeni interfeysləri aşağıdakı standart kolleksiyalar reallaşdırır:
- ArrayList, LinkedList → SequencedCollection
- LinkedHashSet, TreeSet → SequencedSet
- LinkedHashMap, TreeMap → SequencedMap
Bu o deməkdir ki, əgər siz artıq bu kolleksiyalardan istifadə edirsinizsə, avtomatik olaraq yeni imkanlar əldə edirsiniz!
2. SequencedCollection, SequencedSet, SequencedMap üçün əsas metodlar
Metodlar: SequencedCollection
E getFirst(); // Birinci elementi əldə et
E getLast(); // Son elementi əldə et
SequencedCollection<E> reversed(); // Kolleksiyanı tərsinə qaydada təqdim et
Metodlar: SequencedSet
SequencedCollection üçün olan eyni metodlar, üstəlik Setin təqdim etdikləri.
Metodlar: SequencedMap
Map.Entry<K, V> firstEntry(); // Birinci element (açar-dəyər)
Map.Entry<K, V> lastEntry(); // Son element (açar-dəyər)
SequencedMap<K, V> reversed(); // Xəritə əks ardıcıllıqla
3. Yeni interfeyslərin istifadəsinə nümunələr
Nümunə 1: Birinci və sonuncu elementin alınması
import java.util.*;
public class SequencedDemo {
public static void main(String[] args) {
SequencedCollection<String> sc = new ArrayList<>();
sc.add("Java");
sc.add("Python");
sc.add("Kotlin");
// Birinci və sonuncu elementi əldə et
String first = sc.getFirst(); // "Java"
String last = sc.getLast(); // "Kotlin"
System.out.println("Birinci: " + first);
System.out.println("Sonuncu: " + last);
}
}
Nəticə:
Birinci: Java
Sonuncu: Kotlin
Nümunə 2: Kolleksiyanı tərsinə çevirmək
SequencedCollection<String> sc = new LinkedList<>();
sc.add("A");
sc.add("B");
sc.add("C");
SequencedCollection<String> reversed = sc.reversed();
System.out.println(reversed); // [C, B, A]
Nəzərə alın: reversed() kolleksiyanın əks ardıcıllıqda təqdimatını qaytarır. Əgər ilkin kolleksiyanı dəyişsəniz, reversed təqdimatı da dəyişəcək!
Nümunə 3: SequencedSet ilə işləmək
SequencedSet<Integer> set = new LinkedHashSet<>();
set.add(100);
set.add(200);
set.add(300);
System.out.println("Birinci element: " + set.getFirst()); // 100
System.out.println("Son element: " + set.getLast()); // 300
SequencedSet<Integer> reversedSet = set.reversed();
System.out.println(reversedSet); // [300, 200, 100]
Nümunə 4: SequencedMap ilə işləmək
SequencedMap<String, Integer> map = new LinkedHashMap<>();
map.put("apple", 5);
map.put("banana", 3);
map.put("cherry", 7);
Map.Entry<String, Integer> first = map.firstEntry();
Map.Entry<String, Integer> last = map.lastEntry();
System.out.println("Birinci: " + first.getKey() + " = " + first.getValue()); // apple = 5
System.out.println("Sonuncu: " + last.getKey() + " = " + last.getValue()); // cherry = 7
SequencedMap<String, Integer> reversedMap = map.reversed();
System.out.println(reversedMap); // {cherry=7, banana=3, apple=5}
4. Bu, sizin tətbiqinizlə necə bağlıdır?
Tutaq ki, tədris tətbiqinizdə sistemə daxil olan istifadəçilərin siyahısını saxlayırsınız və birinci və sonuncu istifadəçini tez əldə etmək istəyirsiniz (məsələn, “kim ilk daxil oldu” və “kim ən sonda”). Əvvəllər belə bir şey yazmalı olurdunuz:
List<String> users = new ArrayList<>();
// ... istifadəçiləri əlavə edirik
String first = users.get(0);
String last = users.get(users.size() - 1);
Amma kolleksiya siyahı yox, məsələn, LinkedHashSetdirsə (elementlər unikaldır və sıra saxlanılır), bu fənd işləməyəcək:
Set<String> users = new LinkedHashSet<>();
// ... istifadəçiləri əlavə edirik
// Birincini necə əldə etməli? Yalnız iterator vasitəsilə:
String first = users.iterator().next();
// Bəs sonuncunu? Yalnız bütün elementləri keçməklə!
İndi isə hər şey daha sadə və universaldır:
SequencedSet<String> users = new LinkedHashSet<>();
// ... istifadəçiləri əlavə edirik
String first = users.getFirst();
String last = users.getLast();
Bu, təkcə kodun miqdarını azaltmır, həm də onu daha oxunaqlı və təhlükəsiz edir.
5. Yeni interfeyslərin sxemi
classDiagram
Collection <|-- SequencedCollection
List <|-- SequencedCollection
Set <|-- SequencedSet
Map <|-- SequencedMap
SequencedCollection <|-- SequencedSet
SequencedSet <|-- LinkedHashSet
SequencedSet <|-- TreeSet
SequencedCollection <|-- ArrayList
SequencedCollection <|-- LinkedList
SequencedMap <|-- LinkedHashMap
SequencedMap <|-- TreeMap
6. Faydalı nüanslar
SequencedCollection-un praktiki üstünlükləri
- Sıra ilə iş üçün vahid interfeys: Artıq harada get(0) olduğunu, harada iterator lazım gəldiyini və harada ümumiyyətlə birinci elementi almağın mümkün olmadığını yadda saxlamağa ehtiyac yoxdur.
- Növbələr və yığınlarla işləyərkən rahatlıq: Asanlıqla birinci (head) və son (tail) elementi əldə etmək mümkündür.
- Təhlükəsizlik və oxunaqlılıq: Kolleksiyalardan səhv istifadə ilə bağlı xətalar azalır; kod özünü izah edən olur.
- Kolleksiyanın sürətlə tərsinə çevrilməsi: reversed() metodu əl işi olmadan əks ardıcıllığı asanlıqla əldə etməyə imkan verir.
- Kodu saxlamaq və genişləndirmək asanlığı: Gələcəkdə məsələn, ArrayListi LinkedHashSet ilə əvəz etmək istəsəniz, SequencedCollection-dan istifadə edən kodu yenidən yazmağa ehtiyac qalmayacaq.
Reallaşdırma xüsusiyyətləri
- Bütün kolleksiyalar SequencedCollection-u reallaşdırmır: Məsələn, HashSet və HashMap ardıcıllığı təmin etmir, buna görə də yeni interfeysləri reallaşdırmır.
- Metodlar istisna ata bilər: Kolleksiya boşdursa, getFirst() və ya getLast() çağırışı NoSuchElementException atacaq. Kolleksiyanın boş olmadığını yoxlamağı unutmayın!
- reversed() — təqdimatdır, surət deyil: İlkin kolleksiyadakı dəyişikliklər tərsinə təqdimatda, tərsinə təqdimatda edilən dəyişikliklər isə ilkin kolleksiyada əks olunur.
- Uyğunluq: Yeni interfeyslər yalnız Java 21-dən başlayaraq əlçatandır. Əgər daha köhnə Java versiyasından istifadə edirsinizsə, hələlik bu imkanlar sizə uyğun deyil (amma bu, yenilənmək üçün əla səbəbdir!).
- Generics: Bütün yeni interfeyslər generics-i tam dəstəkləyir, beləliklə istənilən məlumat tipləri ilə işləmək mümkündür.
7. SequencedCollection ilə işləyərkən tipik səhvlər
Səhv №1: Ardıcıllıq təmin etməyən kolleksiyalardan ardıcıllıq gözləmək. Əgər siz HashSet-i SequencedSet-ə çevirməyə çalışsanız, kompilyasiya xətası alacaqsınız — HashSet ardıcıllığı təmin etmir və bu interfeysi reallaşdırmır.
Səhv №2: Boş kolleksiyaları nəzərə almamaq. Boş kolleksiyada getFirst() və ya getLast() çağırışı istisna atacaq. Bu metodlara müraciət etməzdən əvvəl kolleksiyanın boş olmadığını yoxlayın:
if (!sc.isEmpty()) {
String first = sc.getFirst();
}
Səhv №3: reversed() ilə bağlı anlaşılmazlıqlar. reversed() metodu surəti deyil, təqdimatı qaytarır. Əgər reversed təqdimatını dəyişsəniz, ilkin kolleksiya da dəyişəcək (və əksinə). Bu davranışı gözləmirsinizsə, gözlənilməz nəticələrə səbəb ola bilər.
Səhv №4: Yeni interfeyslərdən Java-nın köhnə versiyalarında istifadə. Layihəniz Java 21-dən aşağı versiya ilə kompilyasiya olunursa, kompilyator bu interfeysləri tapmayacaq. Layihə ayarlarında JDK versiyasını yoxlayın!
GO TO FULL VERSION