JavaRush /בלוג Java /Random-HE /HashMap בג'אווה - באיזה סוג מפה מדובר?

HashMap בג'אווה - באיזה סוג מפה מדובר?

פורסם בקבוצה
שלום! היום נדבר על מבנה נתונים נוסף - מפה. השם הרוסי הרשמי שלו הוא "מערך אסוציאטיבי", אך אינו משמש לעתים קרובות. האפשרויות הנפוצות יותר הן "מילון", "מפה", או (לרוב) הסלנג האנגליזם "מפה" :) בתוך מפה, הנתונים מאוחסנים בפורמט "מפתח" - "ערך", כלומר בזוגות. גם מפתחות וגם ערכים יכולים להיות כל אובייקט - מספרים, מחרוזות או אובייקטים של מחלקות אחרות.

כיצד מפה שונה ממבני נתונים אחרים

בעבר, בדקנו מבני נתונים שבהם אלמנטים מאוחסנים לבד. במערך, או ArrayList / LinkedList , אנו מאחסנים מספר מסוים של אלמנטים. אבל מה אם המשימה שלנו תשתנה מעט? לדוגמה, תארו לעצמכם שעומדים בפנינו המשימה של יצירת רשימה של 100 אנשים, שבה יישמרו שמו המלא ומספר הדרכון של האדם. באופן עקרוני, זה לא כל כך קשה. לדוגמה, אתה יכול להתאים את שניהם בשורה וליצור רשימה של שורות כך: "אנה איבנובנה רשטניקובה, 4211 717171." אבל לפתרון הזה יש שני חסרונות. ראשית, ייתכן שנצטרך פונקציית חיפוש דרכונים. ועם הפורמט הזה לאחסון מידע, זה יהיה בעייתי. ושנית, שום דבר לא ימנע מאיתנו ליצור שני אנשים שונים עם אותם מספרי דרכון. וזה החיסרון החמור ביותר של הפתרון שלנו. יש לשלול לחלוטין מצבים כאלה; אין שני אנשים עם אותו מספר דרכון. כאן מפה והתכונות המוצהרות שלה באות לעזרתנו (אחסון נתונים בזוג בפורמט "מפתח"-"ערך"). בואו נסתכל על יישום המפה הנפוץ ביותר - מחלקת Java HashMap .HashMap - איזו מין מפה זו?  - 1

יצירת HashMap ב-Java ועבודה עם הכיתה

יישום זה פשוט מאוד ליצירה:
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();

}
כאן יצרנו מילון שבו אלמנטים יאוחסנו בפורמט "מחרוזת מספרים". המספר יהיה המפתח, והמחרוזת תהיה הערך. ציינו גם איזה סוג מפתחות יהיו לנו ( Integer) ואיזה סוג ערכים ( String). למה זה כל כך? ראשית, המפתח ב-HashMap הוא תמיד ייחודי . זה יעבוד מצוין עבורנו כי אנחנו יכולים להשתמש במספר הדרכון כמפתח ולהימנע מכפילויות. והשורה עם השם המלא תשמש כערך (את השם המלא של אנשים שונים אפשר לחזור בקלות, אין בזה שום דבר רע מבחינתנו).

הוספת זוג חדש ל- HashMap

משימה זו נראית כך:
public class Main {

   public static void main(String[] args) {
       HashMap<Integer, String> passportsAndNames = new HashMap<>();


       passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
       passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
       passportsAndNames.put(8082771, "Donald John Trump");
       System.out.println(passportsAndNames);

   }

}
השיטה משמשת לשם כך put(). בנוסף, ל-HashMap יש שיטה עוקפת toString()כך שניתן להדפיס אותה למסוף. הפלט ייראה כך: {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 162348=Ivan Mikhailovich Serebryakov}

תכונות של מפתחות HashMap

עכשיו בואו נבדוק אם המפתחות באמת ייחודיים? בואו ננסה להוסיף אלמנט חדש עם מפתח שכבר נמצא במפה:
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   passportsAndNames.put(8082771, "Donald John Trump");
   passportsAndNames.put(162348, "Viktor Mikhailovich Stychkin");//repeat key

   System.out.println(passportsAndNames);

}
פלט: {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 162348=Viktor Mikhailovich Stychkin} האלמנט הקודם עם מפתח 162348, כפי שאתה יכול לראות, הוחלף. "המפתח" נקרא המפתח מסיבה כלשהי. ערכים ב-HashMap נגישים באמצעות מפתח (אך לא להיפך - לא ניתן להשיג את המפתח לפי ערך, מכיוון שניתן לשכפל ערכים). זה נראה בבירור בדוגמאות של קבלת אלמנט, כמו גם הסרת אלמנט מ-HashMap:
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   passportsAndNames.put(8082771, "Donald John Trump");

   String lidiaName = passportsAndNames.get(212133);
   System.out.println(lidiaName);


   passportsAndNames.remove(162348);
   System.out.println(passportsAndNames);

}
על מנת לקבל ערך או למחוק זוג מהמילון, עלינו להעביר בדיוק את המפתח הייחודי המתאים לערך זה get()לשיטות . אין אינדקסים מספריים, כמו במערכים או ברשימות, ב-HashMap - הערך נגיש באמצעות מפתח. פלט קונסולה: לידיה ארקדייבנה בובליקובה {212133=לידיה ארקדייבנה בובליקובה, 8082771=דונלד ג'ון טראמפ}remove()

בדיקת נוכחות של מפתח וערך

במחלקות ArrayList ו- LinkedList , נוכל לבדוק אם רשימה מכילה אלמנט מסוים. HashMap גם מאפשרת לעשות זאת, ולשני חלקי הזוג: יש לה שיטות containsKey()(בודקת נוכחות של מפתח) ו- containsValue()(בודקת נוכחות של ערך).
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   passportsAndNames.put(8082771, "Donald John Trump");


   System.out.println(passportsAndNames.containsKey(11111));
   System.out.println(passportsAndNames.containsValue("Donald John Trump"));

}
פלט: שקר נכון

קבלת רשימה של כל המפתחות והערכים

תכונה נוחה נוספת של HashMap היא שאתה יכול לקבל בנפרד רשימה של כל המפתחות וכל הערכים . לשם כך, שיטות keySet()ומשמשות values():
public class Main {

   public static void main(String[] args) {

       HashMap<Integer, String> passportsAndNames = new HashMap<>();

       passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
       passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
       passportsAndNames.put(8082771, "Donald John Trump");

       Set<Integer> keys = passportsAndNames.keySet();
       System.out.println("Keys: " + keys);

       ArrayList<String> values = new ArrayList<>(passportsAndNames.values());
       System.out.println("Values: " + values);

   }

}
המפתחות נשלפים לתוך האוסף Set. הייחודיות שלו היא שהוא לא יכול להכיל אלמנטים חוזרים. עכשיו הדבר העיקרי שיש לזכור הוא שניתן להוציא את רשימת כל המפתחות מה-HashMap לאוסף נפרד. בדוגמה, שמרנו את הערכים לרגיל ArrayList. פלט מסוף: מקשים: [212133, 8082771, 162348] ערכים: [לידיה ארקדייבנה בובליקובה, דונלד ג'ון טראמפ, איבן מיכאילוביץ' סרבריקוב] שיטות size()עושות clear()בדיוק אותו דבר כמו במבנים הקודמים שעברנו: הראשונה מחזירה מספר אלמנטים ב המילון ברגע הנוכחי, השני מוחק את כל הרכיבים.
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   passportsAndNames.put(8082771, "Donald John Trump");

   System.out.println(passportsAndNames.size());
   passportsAndNames.clear();
   System.out.println(passportsAndNames);

}
פלט: 3 {} כדי לבדוק אם ה-HashMap שלנו מכיל לפחות אלמנט אחד, נוכל להשתמש בשיטה isEmpty():
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   passportsAndNames.put(8082771, "Donald John Trump");

   if (!passportsAndNames.isEmpty()) {

       System.out.println(passportsAndNames);

   }

}
פלט: {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 162348=Ivan Mikhailovich Serebryakov} כעת נפיק פלט לקונסולה רק לאחר אימות ראשוני :)

שילוב של שתי מפות לאחת

נקודה מעניינת נוספת היא שניתן לשלב שתי מפות לאחת . יש שיטה לזה putAll(). אנו קוראים לזה ב- HashMap הראשון , מעבירים את השני כארגומנט, והאלמנטים מהשני יתווספו לראשון:
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();
   HashMap<Integer, String> passportsAndNames2 = new HashMap<>();

   passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   passportsAndNames.put(8082771, "Donald John Trump");

   passportsAndNames2.put(917352, "Alexey Andreevich Ermakov");
   passportsAndNames2.put(925648, "Maxim Olegovich Arkharov");


   passportsAndNames.putAll(passportsAndNames2);
   System.out.println(passportsAndNames);

}
פלט: {917352=Alexey Andreevich Ermakov, 212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 925648=Maxim Olegovich Arkharov, 162348=Ivan Mikhailovich Serebryakovsall elements toAndNames of passports.AndNames of passports.AndNames of passports עכשיו בואו נסתכל על דוגמה מסובכת יותר. כלומר, לחזור על HashMap בלולאה.
for (Map.Entry entry: passportsAndNames.entrySet()) {

   System.out.println(entry);

}
ממשק Map.Entryפירושו רק צמד מפתח-ערך בתוך מילון. השיטה entrySet()מחזירה רשימה של כל הזוגות ב-HashMap שלנו (מכיוון שהמפה שלנו מורכבת מצמדי Entry כאלה בדיוק, אנו חוזרים על זוגות, ולא בנפרד מפתחות או ערכים). מסקנה: 212133=Lidiya Arkadyevna Bublikova 8082771=Donald John Trump 162348=Ivan Mikhailovich Serebryakov שמור את המאמר הזה לעתיד: https://habr.com/ru/post/128017/ עכשיו זה מוקדם מדי לקרוא אותו, אבל בעתיד , כאשר תשים את ידך על השימוש ב-HashMap, זה יעזור לך להבין איך מבנה הנתונים הזה פועל מבפנים. כמו כן, אל תשכח לבדוק את התיעוד הרשמי של אורקל ב- HashMap.
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION