ממיין HashMap בג'אווה

1. הקדמה

במדריך מהיר זה נלמד כיצד סוג של מפת גיבוב בג'אווה.

באופן ספציפי יותר, נבחן מיון מפת גיבוב ערכים לפי המפתח או הערך שלהם באמצעות:

  • TreeMap
  • רשימת מערך ו Collections.sort ()
  • TreeSet
  • משתמש ב זרם ממשק API, ולבסוף,
  • משתמש ב גויאבה סִפְרִיָה

2. שימוש בא TreeMap

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

בתור התחלה, נגדיר א מפת גיבוב לאתחל אותו בכמה נתונים:

מפת מפה = HashMap חדש (); עובד שכיר 1 = עובד חדש (1L, "Mher"); map.put (עובד 1. getName (), עובד 1); עובד שכיר 2 = עובד חדש (22L, "אנני"); map.put (עובד 2. getName (), עובד 2); עובד שכיר 3 = עובד חדש (8L, "ג'ון"); map.put (עובד 3. getName (), עובד 3); עובד שכיר 4 = עובד חדש (2L, "ג'ורג '"); map.put (עובד 4. getName (), עובד 4);

בשביל ה עוֹבֵד מעמד, שים לב שיישמנו ניתן להשוות:

יישומי שכבה ציבורית מכירים דומים {פרטי מזהה ארוך; שם מחרוזת פרטי; // constructor, getters, setter // לעקוף שווה ו- hashCode @ Override public int CompareTo (עובד שכיר) {return (int) (this.id - עובד.גטיד ()); }}

לאחר מכן, אנו שומרים את הערכים ב- TreeMap באמצעות הבנאי שלו:

TreeMap מיון = TreeMap חדש (מפה);

או ה לשים הכל שיטה להעתקת הנתונים:

TreeMap מיון = TreeMap חדש (); sorted.putAll (מפה);

וזה הכל! כדי לוודא שערכי המפה שלנו ממוינים לפי מפתח, בואו נדפיס אותם:

אנני = עובד {id = 22, שם = "אנני"} ג'ורג '= עובד {id = 2, שם = "ג'ורג'"} ג'ון = עובד {id = 8, שם = "ג'ון"} Mher = עובד {id = 1, name = "Mher"}

כפי שאנו רואים, המפתחות ממוינים לפי סדר טבעי.

3. שימוש רשימת מערך

כמובן שנוכל למיין את ערכי המפה בעזרת רשימת מערך. ההבדל העיקרי מהשיטה הקודמת הוא בכך אנחנו לא מתחזקים את מַפָּה ממשק כאן.

3.1. מיין לפי מפתח

בואו נטען את ערכת המפתחות ל- רשימת מערך:

רשימה של עובדByKey = ArrayList חדש (map.keySet ()); Collections.sort (עובדByKey);

והתפוקה היא:

[אנני, ג'ורג ', ג'ון, מר]

3.2. מיין לפי ערך

עכשיו, מה אם נרצה למיין את ערכי המפה שלנו לפי תְעוּדַת זֶהוּת שדה של עוֹבֵד לְהִתְנַגֵד? אנחנו יכולים להשתמש ב- רשימת מערך גם בשביל זה.

ראשית, בואו נעתיק את הערכים לרשימה:

רשימה של EmployById = ArrayList חדש (map.values ​​());

ואחרי זה, אנחנו ממיינים את זה:

Collections.sort (employeeById);

זכור שזה עובד בגלל עוֹבֵד מיישם את ניתן להשוות מִמְשָׁק. אחרת, עלינו להגדיר משווה ידני לשיחתנו Collections.sort.

כדי לבדוק את התוצאות, אנו מדפיסים את עובדById:

[עובד {id = 1, name = "Mher"}, עובד {id = 2, name = "George"}, עובד {id = 8, name = "John"}, עובד {id = 22, name = "Annie "}]

כפי שאנו רואים, האובייקטים ממוינים לפי שלהם תְעוּדַת זֶהוּת שדה.

4. באמצעות א TreeSet

למקרה שאנחנו לא רוצה לקבל ערכים כפולים באוסף הממוין שלנו, יש פיתרון נחמד עם TreeSet.

ראשית, בואו נוסיף כמה ערכים כפולים למפה הראשונית שלנו:

עובד שכיר 5 = עובד חדש (1L, "Mher"); map.put (עובד 5. getName (), עובד 5); עובד שכיר 6 = עובד חדש (22L, "אנני"); map.put (employee6.getName (), עובד6);

4.1. מיין לפי מפתח

כדי למיין את המפה לפי ערכי המפתח שלה:

SortedSet keySet = TreeSet חדש (map.keySet ());

בואו נדפיס את סט מפתחות וראה את הפלט:

[אנני, ג'ורג ', ג'ון, מר]

עכשיו יש לנו את מקשי המפה מסודרים ללא הכפילויות.

4.2. מיין לפי ערך

כמו כן, עבור ערכי המפה, קוד ההמרה נראה כך:

ערכי SortedSet = TreeSet חדש (map.values ​​());

והתוצאות הן:

[עובד {id = 1, name = "Mher"}, עובד {id = 2, name = "George"}, עובד {id = 8, name = "John"}, עובד {id = 22, name = "Annie "}]

כפי שאנו רואים, אין כפילויות בפלט. זה עובד עם אובייקטים מותאמים אישית כשאנחנו עוקפים שווים ו hashCode.

5. שימוש במבדות וזרמים

מאז Java 8, אנו יכולים להשתמש ב- Stream API ובביטויי lambda כדי למיין את המפה. כל מה שאנחנו צריכים זה להתקשר ל מְמוּיָן שיטה על פני המפה זרם צנרת.

5.1. מיין לפי מפתח

כדי למיין לפי מפתח, אנו משתמשים ב- comparingByKey משווה:

map.entrySet () .stream () .sorted (Map.Entry.comparingByKey ()) .forEach (System.out :: println);

הגמר לכל אחד הבמה מדפיסה את התוצאות:

אנני = עובד {id = 22, שם = "אנני"} ג'ורג '= עובד {id = 2, שם = "ג'ורג'"} ג'ון = עובד {id = 8, שם = "ג'ון"} Mher = עובד {id = 1, name = "Mher"}

כברירת מחדל, מצב המיון עולה.

5.2. מיין לפי ערך

כמובן, אנו יכולים למיין לפי עוֹבֵד גם חפצים:

map.entrySet () .stream () .sorted (Map.Entry.comparingByValue ()) .forEach (System.out :: println);

כפי שאנו רואים, הקוד לעיל מדפיס מפה ממוינת לפי תְעוּדַת זֶהוּת שדות של עוֹבֵד חפצים:

Mher = עובד {id = 1, name = "Mher"} ג'ורג '= עובד {id = 2, name = "George"} ג'ון = עובד {id = 8, name = "John"} אנני = עובד {id = 22, שם = "אנני"}

בנוסף, אנו יכולים לאסוף את התוצאות למפה חדשה:

תוצאת מפה = map.entrySet () .stream () .sorted (Map.Entry.comparingByValue ()) .collect (Collectors.toMap (Map.Entry :: getKey, Map.Entry :: getValue, (oldValue, newValue) - > oldValue, LinkedHashMap :: new));

שים לב שאספנו את התוצאות שלנו ל- a LinkedHashMap. כברירת מחדל, Collectors.toMap מחזיר HashMap חדש, אבל כידוע, מפת גיבוב אינו מבטיח איטרציהלהזמין, בזמן LinkedHashMap עושה.

6. שימוש בגויאבה

לבסוף, ספרייה המאפשרת לנו למיין את מפת גיבוב היא גויאבה. לפני שנתחיל, זה יהיה שימושי לבדוק את הכתיבה שלנו לגבי מפות בגויאבה.

ראשית, בואו נכריז על מזמין כפי שאנחנו רוצים למיין את המפה שלנו לפי עובדיםתְעוּדַת זֶהוּת שדה:

Ordering NaturalOrdering = Ordering.natural () .onResultOf (Functions.forMap (map, null));

עכשיו, כל מה שאנחנו צריכים זה להשתמש ImmutableSortedMap להמחשת התוצאות:

ImmutableSortedMap.copyOf (מפה, הזמנה טבעית);

ושוב, הפלט הוא מפה שהורה על ידי תְעוּדַת זֶהוּת שדה:

Mher = עובד {id = 1, name = "Mher"} ג'ורג '= עובד {id = 2, name = "George"} ג'ון = עובד {id = 8, name = "John"} אנני = עובד {id = 22, שם = "אנני"}

7. סיכום

במאמר זה סקרנו מספר דרכים למיון מפת גיבוב לפי מפתח או לפי ערך.

ובדקנו מקרוב כיצד אנו יכולים לעשות זאת כאשר התכונה היא מחלקה מותאמת אישית על ידי יישום ניתן להשוות.

לבסוף, כמו תמיד, ניתן למצוא את הקוד ששימש במהלך הדיון ב- GitHub.