סינון ושינוי אוספים בגויאבה

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

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

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

2. סנן אוסף

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

@ מבחן ציבורי בטל כאשרFilterWithIterables_thenFiltered () {List names = Lists.newArrayList ("John", "Jane", "Adam", "Tom"); תוצאה ניתנת לניתוח = Iterables.filter (שמות, Predicates.containsPattern ("a")); assertThat (תוצאה, containInAnyOrder ("ג'יין", "אדם")); }

כפי שאתה יכול לראות, אנו מסננים את רשימה של שמות כדי לקבל רק את השמות המכילים את התו "a" - ואנחנו משתמשים Iterables.filter () לעשות זאת.

לחלופין, אנו יכולים להשתמש בו היטב Collections2.filter () ממשק API גם:

@ מבחן ציבורי בטל כאשרFilterWithCollections2_thenFiltered () {List names = Lists.newArrayList ("John", "Jane", "Adam", "Tom"); תוצאת האוסף = Collections2.filter (names, Predicates.containsPattern ("a")); assertEquals (2, result.size ()); assertThat (תוצאה, containInAnyOrder ("ג'יין", "אדם")); result.add ("אנה"); assertEquals (5, names.size ()); }

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

חשוב גם להבין את זה עכשיו, התוצאה מוגבלת על ידי הפרדיקט - אם נוסיף אלמנט שאינו מספק זאת לְבַסֵס, IllegalArgumentException ייזרק:

@Test (צפוי = IllegalArgumentException.class) חלל ציבורי givenFilteredCollection_whenAddingInvalidElement_thenException () {List names = Lists.newArrayList ("John", "Jane", "Adam", "Tom"); תוצאת האוסף = Collections2.filter (names, Predicates.containsPattern ("a")); result.add ("אלביס"); }

3. כתוב מסנן מותאם אישית לְבַסֵס

הבא - בואו נכתוב בעצמנו לְבַסֵס במקום להשתמש באחת שמספקת הספרייה. בדוגמה הבאה - נגדיר פרדיקט שמקבל רק את השמות שמתחילים ב- "A" או "J":

@Test ציבורי בטל כאשרFilterCollectionWithCustomPredicate_thenFiltered () {Predicate predicate = new Predicate () {@Override public boolean apply (קלט מחרוזת) return input.startsWith ("A")}; שמות רשימות = Lists.newArrayList ("ג'ון", "ג'יין", "אדם", "טום"); תוצאת האוסף = Collections2.filter (שמות, פרדיקט); assertEquals (3, result.size ()); assertThat (התוצאה מכילה InAnyOrder ("ג'ון", "ג'יין", "אדם")); }

4. שלבו מספר חזויות

נוכל לשלב מספר חיזויים מרובים באמצעות Predicates.or () ו Predicates.and ().

בדוגמה הבאה - אנו מסננים א רשימה של שמות כדי לקבל את השמות שמתחילים ב- "J" או שאינם מכילים "a":

@ מבחן ציבורי בטל כאשרFilterUsingMultiplePredicates_thenFiltered () {List names = Lists.newArrayList ("John", "Jane", "Adam", "Tom"); תוצאת האוסף = Collections2.filter (שמות, Predicates.or (Predicates.containsPattern ("J"), Predicates.not (Predicates.containsPattern ("a")))); assertEquals (3, result.size ()); assertThat (התוצאה מכילה InAnyOrder ("ג'ון", "ג'יין", "טום")); }

5. הסר ערכים אפסים בזמן סינון אוסף

אנחנו יכולים לנקות את ריק ערכים מאוסף על ידי סינון עם Predicates.notNull () כמו בדוגמה הבאה:

@ מבחן ציבורי בטל כאשר RemovNullFromCollection_thenRemoved () {List names = Lists.newArrayList ("John", null, "Jane", null, "Adam", "Tom"); תוצאת האוסף = Collections2.filter (names, Predicates.notNull ()); assertEquals (4, result.size ()); assertThat (התוצאה מכילה InAnyOrder ("ג'ון", "ג'יין", "אדם", "טום")); }

6. בדוק אם כל האלמנטים באוסף תואמים לתנאי

לאחר מכן, בואו נבדוק אם כל האלמנטים באוסף תואמים למצב מסוים. נשתמש Iterables.all () כדי לבדוק אם כל השמות מכילים "n" או "m", נבדוק אם כל האלמנטים מכילים "a":

@Test הציבור בטל כאשרCheckingIfAllElementsMatchACondition_thenCorrect () m ")); assertTrue (result); result = Iterables.all (names, Predicates.containsPattern (" a ")); assertFalse (result); 

7. להפוך אוסף

עכשיו - בואו נראה איך להפוך אוסף באמצעות גויאבה פוּנקצִיָה. בדוגמה הבאה - אנו הופכים א רשימה של שמות ל- a רשימה שֶׁל שלמים (אורך השם) עם Iterables.transform ():

@ מבחן ציבורי בטל whenTransformWithIterables_thenTransformed () {פונקציית פונקציה = פונקציה חדשה () {@Override שלם ציבורי חל (קלט מחרוזת) {return input.length (); }}; שמות רשימות = Lists.newArrayList ("ג'ון", "ג'יין", "אדם", "טום"); תוצאה ניתנת לשינוי = Iterables.transform (שמות, פונקציה); assertThat (תוצאה, מכיל (4, 4, 4, 3)); }

אנחנו יכולים גם להשתמש ב- Collections2.transform () ממשק API כמו בדוגמה הבאה:

@Test הציבור בטל כאשרTransformWithCollections2_thenTransformed () {פונקציה func = פונקציה חדשה () {@Override שלם ציבורי להחיל (קלט מחרוזת) {return input.length (); }}; שמות רשימות = Lists.newArrayList ("ג'ון", "ג'יין", "אדם", "טום"); תוצאת האוסף = Collections2.transform (שמות, פונקציה); assertEquals (4, result.size ()); assertThat (תוצאה, מכיל (4, 4, 4, 3)); תוצאה.הסר (3); assertEquals (3, names.size ()); }

שים לב שהפלט של Collections.transform () הוא תצוגה חיה של המקור אוסף- שינויים האחד משפיע על השני.

וכמו כן - אם ננסה להוסיף אלמנט לפלט אוסף, לא נתמךOperationException ייזרק.

8. צור פוּנקצִיָה מ לְבַסֵס

אנחנו יכולים גם ליצור פוּנקצִיָה מ לְבַסֵס באמצעות Functions.fromPredicate (). זו, כמובן, תהיה פונקציה שהופכת את התשומות ל בוליאני, על פי מצב הפרדיקט.

בדוגמה הבאה אנו הופכים את a רשימה שמות לרשימת בוליאנים שכל אלמנט מייצג אם השם מכיל "m":

@ מבחן ציבורי בטל כאשרCreatingAFunctionFromAPredicate_thenCorrect () {List names = Lists.newArrayList ("John", "Jane", "Adam", "Tom"); תוצאת האוסף = Collections2.transform (שמות, Functions.forPredicate (Predicates.containsPattern ("m"))); assertEquals (4, result.size ()); assertThat (תוצאה, מכיל (שקר, שקר, נכון, נכון)); }

9. הרכב שתי פונקציות

לאחר מכן - בואו נסתכל כיצד להפוך אוסף באמצעות הלחנה פוּנקצִיָה.

Functions.compose () מחזיר את הרכב שתי פונקציות כפי שהוא חל על השנייה פוּנקצִיָה על הפלט של הראשון פוּנקצִיָה.

בדוגמה הבאה - הראשונה פוּנקצִיָה להפוך את השם לאורכו, ואז לשני פוּנקצִיָה הופך את האורך ל- a בוליאני ערך המייצג אם אורך השם הוא שווה:

@ מבחן ציבורי בטל כאשרTransformingUsingComposedFunction_thenTransformed () {פונקציה f1 = פונקציה חדשה () {@Override שלם ציבורי החל (קלט מחרוזת) {return input.length (); }}; פונקציה f2 = פונקציה חדשה () {@ ביטול ציבורי בוליאני להחיל (קלט שלם) {קלט החזרה% 2 == 0; }}; שמות רשימות = Lists.newArrayList ("ג'ון", "ג'יין", "אדם", "טום"); תוצאת האוסף = Collections2.transform (שמות, Functions.compose (f2, f1)); assertEquals (4, result.size ()); assertThat (תוצאה, מכיל (נכון, נכון, נכון, שקר)); }

10. שלב סינון והפיכה

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

בדוגמה הבאה - אנו מסננים את ה- רשימה של שמות ואז להפוך אותו באמצעות זורם אינטרטיבי:

@Test הציבור בטל כאשרFilteringAndTransformingCollection_thenCorrect () {Predicate predicate = new Predicate () {@Override בוליאני ציבורי להחיל (קלט מחרוזת)}; פונקציה func = פונקציה חדשה () {@Override ציבור שלם החל (קלט מחרוזת) {return input.length (); }}; שמות רשימות = Lists.newArrayList ("ג'ון", "ג'יין", "אדם", "טום"); תוצאת האוסף = FluentIterable.from (names) .filter (predicate) .transform (func) .toList (); assertEquals (2, result.size ()); assertThat (תוצאה, מכיל InAnyOrder (4, 3)); }

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

11. מסקנה

לבסוף למדנו כיצד לסנן ולהפוך אוספים באמצעות גויאבה. השתמשנו ב- Collections2.filter () ו Iterables.filter () ממשקי API לסינון וכן Collections2.transform () ו Iterables.transform () להפוך אוספים.

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

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


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