JavaRush /בלוג Java /Random-HE /9 השאלות המובילות על מפה ב-Java
Treefeed
רָמָה

9 השאלות המובילות על מפה ב-Java

פורסם בקבוצה
זכור כי מפה היא נתונים מובנים המורכבים מקבוצה של צמדי מפתח-ערך, וניתן להשתמש בכל מפתח רק פעם אחת במפה אחת. נושא זה מכסה 9 שאלות בסיסיות על שימוש במפה ב-Java ובמחלקות המיושמות שלה. למען הפשטות, אשתמש בהכללות בדוגמאות . לכן, אני אכתוב פשוט Map, מבלי לציין את מפרט המפה. אבל אתה יכול להניח ששני הערכים של K ו- V ברי השוואה, כלומר K מרחיב Comparable ו- V מרחיב גם Comparable .9 השאלות המובילות על מפה ב-Java - 1

0. המרת מפה לרשימה

ב-Java, ממשק המפה מציע שלושה סוגים של אוספים: ערכת מפתחות, ערכת ערכים וערכת מפתח-ערך. ניתן להפוך את כולם לרשימה באמצעות הבנאי או השיטה addAll(). קטע הקוד הבא מדגים כיצד ליצור ArrayList ממפה.
// list of keys
List keyList = new ArrayList(Map.keySet());
//list of values
List valueList = new ArrayList(Map.valueSet());
//list key-value
List entryList = new ArrayList(Map.entrySet());

1. עברו בלולאה בין כל הערכים במפה

מעבר על כל זוג מפתח-ערך הוא ההליך הבסיסי והבסיסי ביותר להליכה במפה. ב-Java, כל זוג מאוחסן בשדה Map בשם Map.Entry . Map.entrySet()מחזירה קבוצה של ערכי מפתח, כך שהדרך היעילה ביותר לחזור על כל הערכים של מפה תהיה:
for(Entry entry: Map.entrySet()) {
  //get the key
  K key = entry.getKey();
  //get value
  V value = entry.getValue();
}
אנחנו יכולים גם להשתמש ב- Iterator, במיוחד בגרסאות צעירות מ-JDK 1.5
Iterator itr = Map.entrySet().iterator();
while(itr.hasNext()) {
  Entry entry = itr.next();
  //get the key
  K key = entry.getKey();
  //get value
  V value = entry.getValue();
}

2. הזמנת מפה לפי Keys

ארגון מפות לפי מקשים הוא הליך נפוץ נוסף. הדרך הראשונה היא להוסיף את Map.Entry לרשימה, ולמיין באמצעות משווה שממיין לפי ערכים.
List list = new ArrayList(Map.entrySet());
Collections.sort(list, new Comparator() {

  @Override
  public int compare(Entry e1, Entry e2) {
    return e1.getKey().compareTo(e2.getKey());
  }
});
דרך נוספת: השתמשו ב- SortedMap , שבנוסף לכך, גם מסדרת את המפתחות שלה לפי הסדר. אבל, כל המפתחות חייבים לכלול Comparable או להיות מקובלים על ידי המשווה. אחת המחלקות המיושמות SortedMapהיא TreeMap . הקונסטרוקטור שלו מקבל משווה. הקוד הבא מראה כיצד להפוך אחד רגיל Mapלמסודר.
SortedMap sortedMap = new TreeMap(new Comparator() {

  @Override
  public int compare(K k1, K k2) {
    return k1.compareTo(k2);
  }

});
sortedMap.putAll(Map);

3. הזמינו מפה לפי ערכים

הוספת מפה לרשימה ולאחר מכן מיון שלה עובד במקרה זה, אבל הפעם אתה צריך להשתמש Entry.getValue(). הקוד למטה כמעט זהה לקודם.
List list = new ArrayList(Map.entrySet());
Collections.sort(list, new Comparator() {

  @Override
  public int compare(Entry e1, Entry e2) {
    return e1.getValue().compareTo(e2.getValue());
  }

});
אנחנו עדיין יכולים להשתמש בו SortedMapבמקרה זה, אבל רק אם הערכים הם ייחודיים. במקרה זה, תוכל להפוך את צמד המפתח-ערך לערך-מפתח. לפתרון זה יש מגבלות חמורות ואינו מומלץ על ידי.

4. אתחול מפה סטטית/בלתי ניתנת לשינוי

כאשר אתה רוצה שמפה תישאר בלתי ניתנת לשינוי, דרך טובה היא להעתיק אותה למפה בלתי ניתנת לשינוי. טכניקת תכנות הגנתי זו תעזור לך ליצור מפה שהיא לא רק בטוחה לשימוש, אלא גם בטוחה לשרשור. כדי לאתחל מפה סטטית/בלתי ניתנת לשינוי, אנו יכולים להשתמש באתחול static(ראה להלן). הבעיה עם הקוד הזה היא שלמרות שהמפה הוכרזה כ- static final, אנחנו עדיין יכולים לעבוד איתו לאחר האתחול, למשל Test.Map.put(3,"three");. אז זה לא חוסר שינוי אמיתי. כדי ליצור מפה בלתי ניתנת לשינוי באמצעות אתחול סטטי, אנו זקוקים למחלקה סופר אנונימית, אותה נוסיף למפה הניתנת לשינוי בשלב האתחול האחרון. נא להסתכל על החלק השני של הקוד. כאשר UnsupportedOperationException ייזרק אם תפעיל את Test.Map.put(3,"three");.
public class Test {

  private static final Map Map;
  static {
    Map = new HashMap();
    Map.put(1, "one");
    Map.put(2, "two");
  }
}
public class Test {

  private static final Map Map;
  static {
    Map aMap = new HashMap();
    aMap.put(1, "one");
    aMap.put(2, "two");
    Map = Collections.unmodifiableMap(aMap);
  }
}
ספריית Guava תומכת גם בדרכים שונות לאתחול אוספים סטטיים ובלתי ניתנים לשינוי. למידע נוסף על היתרונות של כלי השירות לאוספים בלתי ניתנים לשינוי של Guava, עיין בסעיף אוספים בלתי ניתנים לשינוי במדריך ה-Guava .

5. ההבדל בין HashMap, TreeMap ו-Hashtable

ישנם שלושה יישומים עיקריים של ממשק Map ב-Java: HashMap , TreeMap ו- Hashtable . ההבדלים העיקריים הם כדלקמן:
  • סדר המעבר . HashMap ו- HashTable אינם מבטיחים את הזמנת המפה; במיוחד, הם לא מבטיחים שההזמנה תישאר זהה לאורך זמן. אבל TreeMapזה יסדר את כל הערכים ב"סדר הטבעי" של המפתחות או לפי משווה.
  • צמדי מפתח-ערך חוקיים. HashMapמאפשר לך לקבל מפתח null וערך null. HashTableאינו מאפשר מפתח null או ערך null. אם TreeMapנעשה שימוש בסדר טבעי או שהמשווה אינו מאפשר מפתח null, ייגרם חריג.
  • סנכרון . רק HashTableמסונכרן, השאר לא. אבל, "אם אין צורך ביישום בטוח בשרשור, מומלץ להשתמש ב " HashMapבמקום זאת HashTable.
השוואה מפורטת יותר
.                       | HashMap | HashTable | TreeMap
-------------------------------------------------------

Упорядочивание          |нет      |нет        | да
null в ключ-meaning    | да-да   | нет-нет   | нет-да
синхронизировано        | нет     | да        | нет
производительность      | O(1)    | O(1)      | O(log n)
воплощение              | корзины | корзины   | красно-чёрное дерево
קרא עוד על מערכת היחסים HashMap לעומת מערכת היחסים. TreeMap לעומת Hashtable לעומת LinkedHashMap .

6. מפה עם חיפוש הפוך/תצוגה

לפעמים, אנחנו צריכים קבוצה של צמדי מפתח-מפתח, מה שאומר שהערכים הם ייחודיים כמו המפתחות (דפוס אחד לאחד). עקביות זו מאפשרת לך ליצור "תצוגה/חיפוש הפוך" במפה. כלומר, אנו יכולים למצוא מפתח לפי ערכו. מבנה נתונים זה נקרא מפה דו-כיוונית , שלמרבה הצער אינה נתמכת על ידי ה-JDK. גם Apache Common Collections וגם Guava מציעים יישומי מפה דו-כיוונית הנקראים BidiMap ו-BiMap, בהתאמה. שניהם מציגים אילוץ האוכף מיפוי 1:1 בין מפתחות וערכים.

7. עותק רדוד של המפה

כמעט כל, אם לא כולם, מפות ב-Java מכילות בונה העתקה עבור מפה אחרת. אבל הליך ההעתקה אינו מסונכרן. מה שאומר שכשרשור אחד מעתיק מפה, שרשור אחר יכול לשנות את המבנה שלו. כדי למנוע ביטול סנכרון פתאומי של העתקה, יש להשתמש באחד מהם במקרה כזה Collections.synchronizedMap().
Map copiedMap = Collections.synchronizedMap(Map);
דרך מעניינת נוספת להעתיק בצורה רדודה היא להשתמש ב- clone(). אבל זה לא מומלץ אפילו על ידי היוצר של מסגרת אוספי Java, ג'ושוע בלוך. בוויכוח " Copy Constructor vs. Cloning ", הוא נוקט בעמדה: ציטוט: "לעיתים קרובות אני מספק שיטת שיבוט ציבורי בשיעורי בטון כי אנשים מצפים שהם יהיו שם... חבל שהשיבוט מקולקל, אבל זה קרה... שיבוט הוא נקודת תורפה, ואני חושב שצריך להזהיר אנשים לגבי המגבלות שלו". מסיבה זו, אני אפילו לא מראה לך כיצד להשתמש בשיטה clone()להעתקת מפה

8. צור מפה ריקה

אם Mapניתן לשינוי, השתמש ב:
Map = Collections.emptyMap();
לחלופין, השתמש בכל התגלמות אחרת. לדוגמה:
Map = new HashMap();
סוֹף
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION