Salam! Bu gün Xəritə ilə bağlı ən çox yayılmış suallara cavab verəcəyik, amma əvvəlcə bunun nə olduğunu xatırlayaq. Xəritə interfeysi ilə bağlı ən populyar suallara cavablar - 1Xəritə bir sıra açar-dəyər cütlərini ehtiva edən məlumat strukturudur. Onun məlumat strukturu lüğətə bənzəyir, buna görə də onu tez-tez belə adlandırırlar. Eyni zamanda, Map bir interfeysdir və standart jdk-də əsas tətbiqləri ehtiva edir: Hashmap, LinkedHashMap, Hashtable, TreeMap. Ən çox istifadə edilən tətbiq Hashmap-dır, ona görə də nümunələrimizdə istifadə edəcəyik. Xəritənin standart yaradılması və doldurulması belə görünür:
Map<Integer, String> map = new HashMap<>();
map.put(1, "string 1");
map.put(2, "string 2");
map.put(3, "string 3");
Dəyərləri açarla necə əldə etmək olar:
String string1 = map.get(1);
String string2 = map.get(2);
String string3 = map.get(3);
Yuxarıda göstərilənlərin hamısı aydındırsa, populyar suallara cavablarımıza davam edək!

0. Bütün Xəritə dəyərləri arasında təkrarlama necə

Dəyərləri təkrarlamaq xəritələrlə həyata keçirdiyiniz ən ümumi əməliyyatdır. Bütün açar-dəyər cütləri daxili Map.Entry interfeysində saxlanılır və onları əldə etmək üçün siz entrySet(). O, dönə bilən cütlər dəstini qaytarır:
for(Map.Entry<Integer, String> entry: map.entrySet()) {
   // get key
   Integer key = entry.getKey();
   // get value
   String value = entry.getValue();
}

Или используя итератор:
Iterator<Map.Entry<Integer, String>> itr = map.entrySet().iterator();
while(itr.hasNext()) {
   Map.Entry<Integer, String> entry =  itr.next();
   // get key
   Integer key = entry.getKey();
   // get value
   String value = entry.getValue();
}

1. Xəritəni Siyahıya necə çevirmək olar

Xəritə interfeysində elementlərin siyahısını qaytaran 3 üsul var:
  • keySet() - düymələr dəstini qaytarır;
  • values() - dəyərlər toplusunu qaytarır;
  • entrySet() - açar-dəyər dəstləri dəstini qaytarır.
Sinfin konstruktorlarına baxsanız ArrayList, Kolleksiya tipli arqumenti olan konstruktorun olduğunu görəcəksiniz. Set Kolleksiyanın nəslindən olduğu üçün yuxarıda göstərilən bütün metodların nəticələri sinfin konstruktoruna ötürülə bilər ArrayList. Beləliklə, biz yeni siyahılar yaradacağıq və onları aşağıdakı dəyərlərlə dolduracağıq Map:
// key list
List<Integer> keyList = new ArrayList<>(map.keySet());
// value list
List<String> valueList = new ArrayList<>(map.values());
// key-value list
List<Map.Entry<Integer, String>> entryList = new ArrayList<>(map.entrySet());

2. Xəritə düymələrini necə çeşidləmək olar

Xəritələrin çeşidlənməsi də proqramlaşdırmada kifayət qədər geniş yayılmış əməliyyatdır. Bunu bir neçə yolla edə bilərsiniz:
  1. Map.Entry-ni siyahıya qoyun və Comparator istifadə edərək çeşidləyin .

    Müqayisədə biz yalnız cütlərin açarlarını müqayisə edəcəyik:

    List> list = new ArrayList(map.entrySet());
    Collections.sort(list, new Comparator<Map.Entry<Integer, String>>() {
       @Override
       public int compare(Map.Entry<Integer, String> o1, Map.Entry<Integer, String> o2) {
           return o1.getKey() - o2.getKey();
       }
    });
    

    Lambdaları başa düşsəniz, bu giriş əhəmiyyətli dərəcədə qısaldıla bilər:

    Collections.sort(list, Comparator.comparingInt(Map.Entry::getKey));
  2. SortedMap, daha dəqiq desək, TreeMapkonstruktorunda Comparator qəbul edən onun həyata keçirilməsindən istifadə edin . Bu müqayisəedici xəritə düymələrinə tətbiq olunacaq, ona görə də düymələr interfeysi həyata keçirən siniflər olmalıdır Comparable:

    SortedMap<Integer, String> sortedMap = new TreeMap<>(new Comparator<Integer>() {
       @Override
       public int compare(Integer o1, Integer o2) {
           return o1 - o2;
       }
    });

    Və təbii ki, hər şey lambdalardan istifadə edərək yenidən yazıla bilər:

    SortedMap<Integer, String> sortedMap = new TreeMap<>(Comparator.comparingInt(o -> o));

    Birinci üsuldan fərqli olaraq, SortedMap istifadə edərək, biz həmişə məlumatları çeşidlənmiş formada saxlayacağıq.

3. Xəritə qiymətlərini necə çeşidləmək olar

Burada açarlar üçün birinciyə bənzər bir yanaşma istifadə etməlisiniz - dəyərlərin siyahısını əldə edin və siyahıda sıralayın:
List <Map.Entry<Integer, String>> valuesList = new ArrayList(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<Integer, String>>() {
   @Override
   public int compare(Map.Entry<Integer, String> o1, Map.Entry<Integer, String> o2) {
       return o1.getValue().compareTo(o2.getValue());
   }
});
Və bunun üçün lambda belə görünür:
Collections.sort(list, Comparator.comparing(Map.Entry::getValue));

4. HashMap, TreeMap və Hashtable arasındakı fərq nədir

Daha əvvəl qeyd edildiyi kimi, Map interfeysinin 3 əsas tətbiqi var. Onların hər birinin öz xüsusiyyətləri var:
  1. Elementlərin sırası. HashMapHashtablemaddələrin əlavə olunduğu qaydada saxlanacağına zəmanət verməyin. Bundan əlavə, onlar elementlərin sırasının zamanla dəyişməyəcəyinə zəmanət vermirlər. Öz növbəsində, TreeMapelementlərin əlavə olunduğu ardıcıllıqla və ya verilmiş müqayisəçiyə uyğun olaraq saxlanmasına zəmanət verir.

  2. Etibarlı dəyərlər. HashMapaçar və null dəyərə malik olmağa imkan verir, HashTableyox. TreeMap yalnız müqayisəçi icazə verdiyi halda null dəyərlərdən istifadə edə bilər. Müqayisədən istifadə etmədən (əlavə olunduğu ardıcıllıqla cütləri saxlamaqla) null icazə verilmir.

  3. Sinxronizasiya. Yalnız HashTablesinxronlaşdırılıb, qalanları deyil. Xəritəyə müxtəlif mövzular tərəfindən daxil olmaq mümkün olmayacaqsa, HashTable əvəzinə HashMap istifadə etmək tövsiyə olunur.

Və tətbiqlərin ümumi müqayisəsi:
HashMap HashTable TreeMap
Elementlərin sırası Yox Yox Bəli
dəyər kimi null Bəli Yox Həqiqətən yox
İp təhlükəsizliyi Yox Bəli Yox
Elementlərin axtarışının alqoritmik mürəkkəbliyi O(1) O(1) O(log n)
Başlıq altında məlumat strukturu hash cədvəli hash cədvəli qırmızı-qara ağac

5. İki istiqamətli xəritə necə yaradılır

Bəzən həm açarların, həm də dəyərlərin unikal olacağı, yəni xəritədə açar-açar cütlərinin olacağı məlumat strukturundan istifadə etmək lazım gəlir. Bu məlumat strukturu xəritədə “ters çevrilmiş görünüş/axtarış” yaratmağa imkan verir. Yəni biz açarı onun dəyərinə görə tapa bilərik.Bu məlumat strukturu iki istiqamətli xəritə adlanır, təəssüf ki, JDK tərəfindən dəstəklənmir. Ancaq xoşbəxtlikdən, onun həyata keçirilməsini Apache Common Collections və ya Guava kitabxanalarında tapmaq olar. Orada müvafiq olaraq BidiMap və BiMap adlanır. Bu tətbiqlər açarların və dəyərlərin unikallığına məhdudiyyətlər qoyur. Bu, bir-bir əlaqə yaradır.

6. Boş Xəritəni necə yaratmaq olar

Boş xəritə yaratmağın iki yolu var:
  1. Normal obyektin işə salınması:

    Map<Integer, String> emptyMap = new HashMap<>();
  2. Dəyişməz boş xəritə yaratmaq:

    Map<Integer, String> emptyMap =  Collections.emptyMap();
Belə bir xəritəyə məlumat əlavə etməyə çalışdığımız zaman alacağıq: UnsupportedOperationExceptionistisna. Bu yazıda Xəritə interfeysindən istifadə edərkən yarana biləcək ən ümumi suallara baxdıq.