Java 8 Collectors toMap

1. הקדמה

במדריך מהיר זה נדבר על ה- למפות() שיטת ה- אספנים מעמד. נשתמש בזה לאיסוף זרםs לתוך א מַפָּה למשל.

עבור כל הדוגמאות המכוסות כאן, נשתמש ברשימת ספרים כנקודת מוצא ונהפוך אותה לשונה מַפָּה יישומים.

2. רשימה ל מַפָּה

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

שֶׁלָנוּ סֵפֶר מחלקה מוגדרת כ:

כיתת ספר {שם מחרוזת פרטי; פרסום אינטימי פרטי שנה; מחרוזת פרטית isbn; // גטרים וקובעים}

ואנחנו ניצור רשימת ספרים שתאמת את הקוד שלנו:

רשימת ספרים רשימה = ArrayList חדש (); bookList.add (ספר חדש ("אחוות הטבעת", 1954, "0395489318")); bookList.add (ספר חדש ("שני המגדלים", 1954, "0345339711")); bookList.add (ספר חדש ("שובו של המלך", 1955, "0618129111"));

עבור תרחיש זה נשתמש בעומס יתר הבא של ה- למפות() שיטה:

אַסְפָן toMap (Function keyMapper, Function valueMapper)

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

רשימת מפות ציבוריתToMap (רשימת ספרים) {return books.stream (). collect (Collectors.toMap (ספר :: getIsbn, ספר :: getName)); }

ונוכל לאמת שזה עובד עם:

@ מבחן ציבורי בטל כאשר ConvertFromListToMap () {assertTrue (convertToMap.listToMap (booklist) .size () == 3); }

3. פתרון עימותים מרכזיים

הדוגמה שלעיל עבדה היטב, אך מה יקרה אם יש מפתח כפול?

בואו נדמיין שקידמנו את שלנו מַפָּה על ידי כל אחד סֵפֶרשנת יציאה:

רשימת מפות ציבוריתToMapWithDupKeyError (רשימת ספרים) {להחזיר books.stream (). collect (Collectors.toMap (ספר :: getReleaseYear, Function.identity ())); }

בהתחשב ברשימת הספרים הקודמת שלנו, נראה IllegalStateException:

@Test (צפוי = IllegalStateException.class) בטל בציבור כאשר MapHasDuplicateKey_without_merge_function_then_runtime_exception () {convertToMap.listToMapWithDupKeyError (booklist); }

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

אספן toMap (פונקציית keyMapper, value valueMapper, BinaryOperator mergeFunction) 

בואו ונציג פונקציית מיזוג המציינת שבמקרה של התנגשות, אנו שומרים על הערך הקיים:

רשימת מפות ציבוריתToMapWithDupKey (רשימת ספרים) {להחזיר books.stream (). אסוף (Collectors.toMap (ספר :: getReleaseYear, Function.identity (), (קיים, החלפה) -> קיים)); }

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

@Test הציבור בטל כאשר MapHasDuplicateKeyThenMergeFunctionHandlesCollision () {Map booksByYear = convertToMap.listToMapWithDupKey (booklist); assertEquals (2, booksByYear.size ()); assertEquals ("0395489318", booksByYear.get (1954) .getIsbn ()); }

4. סוגי מפות אחרים

כברירת מחדל, א למפות() השיטה תחזיר א מפת גיבוב.

אך האם אנו יכולים לחזור אחרת מַפָּה יישומים? התשובה היא כן:

אספן toMap (פונקציית keyMapper, value valueMapper, BinaryOperator mergeFunction, ספק ספקים)

איפה ה mapSupply היא פונקציה המחזירה חדש, ריק מַפָּה עם התוצאות.

4.1. רשימה ל ConcurrentMap

בוא ניקח את אותה דוגמה כמו לעיל ונוסיף a mapSupply פונקציה להחזרת א ConcurrentHashMap:

רשימת מפות ציבוריתToConcurrentMap (רשימת ספרים) {return books.stream (). collect (Collectors.toMap (Book :: getReleaseYear, Function.identity (), (o1, o2) -> o1, ConcurrentHashMap :: new)); }

נמשיך ונבדוק את הקוד שלנו:

@ מבחן ציבורי בטל כאשרCreateConcurrentHashMap () {assertTrue (convertToMap.listToConcurrentMap (bookList) מופע של ConcurrentHashMap); }
4.2. מְמוּיָן מַפָּה

לבסוף, בואו נראה כיצד להחזיר מפה ממוינת. לשם כך נשתמש ב- TreeMap כ mapSupply פָּרָמֶטֶר.

בגלל TreeMap ממוין לפי הסדר הטבעי של המפתחות שלו כברירת מחדל, אנחנו לא צריכים למיין את המפורש ספרים בְּעָצמֵנוּ:

רשימת TreeMap ציבוריתToSortedMap (ספרים ברשימה) {return books.stream () .collect (Collectors.toMap (Book :: getName, Function.identity (), (o1, o2) -> o1, TreeMap :: new)); }

אז במקרה שלנו, החזר TreeMap ימוין לפי סדר האלף-בית לפי שם הספר:

@ מבחן ציבורי בטל כאשר MapisSorted () {assertTrue (convertToMap.listToSortedMap (bookList) .firstKey (). שווה ("אחוות הטבעת")); }
5. מסקנה

במאמר זה בדקנו את למפות() שיטת ה- אספנים מעמד. זה מאפשר לנו ליצור חדש מַפָּה מ זרם. למדנו גם כיצד לפתור קונפליקטים מרכזיים וליצור יישומי מפות שונים.

כמו תמיד הקוד ניתן להשיג ב- GitHub.


$config[zx-auto] not found$config[zx-overlay] not found