שיטות מפעל הנוחות של Java לאוספים

1. סקירה כללית

Java 9 מביא את הסוכר התחבירי המיוחל ליצירה קטנה שאינה ניתנת לשינוי אוסף מקרים המשתמשים בקו תמציתי אחד. לפי JEP 269, שיטות מפעל נוחות חדשות יכללו ב- JDK 9.

במאמר זה נסקור את השימוש בו יחד עם פרטי היישום.

2. היסטוריה ומוטיבציה

יצירת בלתי משתנה קטנה אוסף בג'אווה מילולית מאוד בדרך המסורתית.

בואו ניקח דוגמא של מַעֲרֶכֶת:

Set set = HashSet חדש (); set.add ("foo"); set.add ("בר"); set.add ("בז"); set = Collections.unmodifiableSet (set);

זה יותר מדי קוד עבור משימה פשוטה וזה אמור להיות אפשרי להיעשות בביטוי יחיד.

האמור לעיל נכון גם לגבי א מַפָּה.

עם זאת, עבור רשימה, יש שיטת מפעל:

רשימת רשימה = Arrays.asList ("foo", "bar", "baz");

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

ישנן דרכים אחרות להפחתת מילוליות כמו אתחול פלטה כפולה טֶכנִיקָה:

Set set = Collections.unmodifiableSet (HashSet חדש () {{add ("foo"); add ("bar"); add ("baz");}});

או באמצעות Java 8 זרמים:

Stream.of ("foo", "bar", "baz") .collect (collectionAndThen (toSet (), Collections :: unmodifiableSet));

טכניקת הפלטה הכפולה רק מעט פחות מילולית אך מפחיתה מאוד את הקריאות (ונחשבת אנטי-דפוסית).

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

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

3. תיאור ושימוש

נקבעו שיטות סטטיות רשימה, מַעֲרֶכֶת, ו מַפָּה ממשקים שלוקחים את האלמנטים כוויכוחים ומחזירים מופע של רשימה, מַעֲרֶכֶת, ו מַפָּה, בהתאמה.

שיטה זו נקראת שֶׁל(…) לכל שלושת הממשקים.

3.1. רשימה ו מַעֲרֶכֶת

החתימה והמאפיינים של רשימה ו מַעֲרֶכֶת שיטות המפעל זהות:

רשימה סטטית של (E e1, E e2, E e3) סט סטטי של (E e1, E e2, E e3)

השימוש בשיטות:

רשימת רשימה = List.of ("foo", "bar", "baz"); Set set = Set.of ("foo", "bar", "baz");

כפי שאנו רואים, זה פשוט מאוד, קצר ותמציתי.

בדוגמה השתמשנו בשיטה עם לוקח בדיוק שלושה אלמנטים כפרמטרים ומחזיר a רשימה / מַעֲרֶכֶת בגודל 3.

אבל יש 12 גרסאות עמוסות של שיטה זו - אחת עשרה עם 0 עד 10 פרמטרים ואחת עם var-args:

רשימה סטטית של () רשימה סטטית של (E e1) רשימה סטטית של (E e1, E e2) // .... וכן הלאה רשימה סטטית של (E ... elems)

למטרות המעשיות ביותר, 10 יסודות יספיקו, אך אם נדרשים יותר, ניתן להשתמש בגרסת var-args.

כעת, אנו עשויים לשאול, מה הטעם שיש 11 שיטות נוספות אם יש גרסה var-args שיכולה לעבוד עבור מספר כלשהו של אלמנטים.

התשובה לכך היא ביצועים. כל קריאת שיטת var-args יוצרת במשתמע מערך. לאחר שהשיטות עמוסות יתר נמנעת מיצירת עצמים מיותרים ומגביית האשפה. לעומת זאת, Arrays.asList תמיד יוצר את המערך הגלום, וכתוצאה מכך הוא פחות יעיל כאשר מספר האלמנטים נמוך.

במהלך יצירת א מַעֲרֶכֶת בשיטת מפעל, אם אלמנטים כפולים מועברים כפרמטרים, אז IllegalArgumentException נזרק בזמן הריצה:

@Test (צפוי = IllegalArgumentException.class) בטל בציבור ב-DuplicateElem_IfIllegalArgExp_thenSuccess () {Set.of ("foo", "bar", "baz", "foo"); }

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

אם עובר מערך מסוג פרימיטיבי, א רשימה שֶׁל מַעֲרָך מאותו סוג פרימיטיבי מוחזר.

לדוגמה:

int [] arr = {1, 2, 3, 4, 5}; רשימת רשימה = List.of (arr);

במקרה זה, א רשימה בגודל 1 מוחזר והאלמנט באינדקס 0 מכיל את המערך.

3.2. מַפָּה

החתימה של מַפָּה שיטת המפעל היא:

מפה סטטית של (K k1, V v1, K k2, V v2, K k3, V v3)

והשימוש:

מפה מפה = Map.of ("foo", "a", "bar", "b", "baz", "c");

דומה ל רשימה ו מַעֲרֶכֶת, ה שֶׁל(…) השיטה עמוסה כדי שיהיו 0 עד 10 זוגות עם ערך מפתח.

במקרה של מַפָּה, יש שיטה אחרת ליותר מעשרה זוגות ערכי מפתח:

מפה סטטית של כניסות (רשומות Map.Entry ...

וזה השימוש:

מפת מפה = Map.ofEntries (new AbstractMap.SimpleEntry ("foo", "a"), AbstractMap.SimpleEntry new ("bar", "b"), AbstractMap.SimpleEntry new ("baz", "c"));

העברת ערכים כפולים עבור מפתח תשליך IllegalArgumentException:

@Test (צפוי = IllegalArgumentException.class) חלל ציבורי givenDuplicateKeys_ifIllegalArgExp_thenSuccess () {Map.of ("foo", "a", "foo", "b"); }

שוב, במקרה של מַפָּה גם הסוגים הפרימיטיביים הם בתיבות אוטומטיות.

4. הערות יישום

האוספים שנוצרו בשיטות המפעל אינם נפוצים ביישומים.

לדוגמא, ה רשימה אינו רשימת מערך וה מַפָּה אינו א מפת גיבוב. אלה יישומים שונים המוצגים בג'אווה 9. יישומים אלה הם פנימיים והבונים שלהם הגבילו את הגישה.

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

4.1. בלתי ניתן לשינוי

האוספים שנוצרו בשיטות המפעל אינם ניתנים לשינוי, ושינוי אלמנט, הוספת אלמנטים חדשים או הסרת אלמנטים זורקים לא נתמךOperationException:

@Test (צפוי = UnsupportedOperationException.class) חלל ציבורי onElemAdd_ifUnSupportedOpExpnThrown_thenSuccess () {Set set = Set.of ("foo", "bar"); set.add ("בז"); }
@Test (צפוי = UnsupportedOperationException.class) חלל ציבורי onElemModify_ifUnSupportedOpExpnThrown_thenSuccess () {List list = List.of ("foo", "bar"); list.set (0, "baz"); } 

מצד שני, האוסף חזר מ Arrays.asListניתן לשינוי. לכן, ניתן לשנות או להסיר את האלמנטים הקיימים. דומה ל רשימה של, איננו יכולים להוסיף אלמנטים חדשים לרשימה שחזרה ממנה Arrays.asList.

@Test (צפוי = UnsupportedOperationException.class) חלל ציבורי ב-ElemRemove_ifUnSupportedOpExpnThrown_thenSuccess () {Map map = Map.of ("foo", "a", "bar", "b"); map.remove ("foo"); }

4.2. לא ריק אלמנט מותר

במקרה של רשימה ו מַעֲרֶכֶת, שום אלמנטים לא יכולים להיות ריק. במקרה של א מַפָּה, לא מקשים ולא ערכים יכולים להיות ריק. חוֹלֵף ריק טיעון זורק א NullPointerException:

@Test (צפוי = NullPointerException.class) חלל ציבורי ב- NullElem_ifNullPtrExpnThrown_thenSuccess () {List.of ("foo", "bar", null); }

בניגוד ל רשימה של, ה Arrays.asList השיטה מקבלת ריק ערכים.

4.3. מקרים מבוססי ערך

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

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

List list1 = List.of ("foo", "bar"); List list2 = List.of ("foo", "bar");

במקרה הזה, רשימה 1 == רשימה 2 יכול להעריך או לא נָכוֹן תלוי ב- JVM.

4.4. סידור

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

5. מסקנה

במאמר זה הצגנו את שיטות המפעל החדשות לאוספים שהוצגו ב- Java 9.

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

לבסוף הבהרנו כי אוספים אלה שונים מהיישומים הנפוצים והצבענו על הבדלים מרכזיים.

קוד המקור המלא ובדיקות היחידות עבור מאמר זה זמינים באתר GitHub.


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