מבוא ל- Java 8 Streams

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

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

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

2. זרם API

אחת התכונות החדשות העיקריות ב- Java 8 היא הצגת פונקציונליות הזרם - java.util.stream - המכיל שיעורים לעיבוד רצפי אלמנטים.

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

2.1. יצירת זרמים

ניתן ליצור זרמים ממקורות אלמנט שונים למשל. אוסף או מערך בעזרת זרם() ו שֶׁל() שיטות:

מחרוזת [] arr = מחרוזת חדשה [] {"a", "b", "c"}; זרם זרם = Arrays.stream (arr); stream = Stream.of ("a", "b", "c");

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

זרם זרם = list.stream (); 

2.2. ריבוי השחלות עם זרמים

ממשק ה- API של Stream גם מפשט ריבוי הליכי משנה באמצעות מתן ה- parallelStream () שיטה שמפעילה פעולות על אלמנטים של זרם במצב מקביל.

הקוד שלמטה מאפשר להפעיל את השיטה תעבוד() במקביל לכל רכיב בזרם:

list.parallelStream (). forEach (אלמנט -> doWork (אלמנט));

בחלק הבא נציג כמה מפעולות ה- API של Stream API בסיסיות.

3. זרם פעולות

ישנן פעולות שימושיות רבות שניתן לבצע בזרם.

הם מחולקים ל פעולות ביניים (לַחֲזוֹר זרם) ו פעולות מסוף (להחזיר תוצאה מסוג מוגדר). פעולות ביניים מאפשרות שרשור.

ראוי גם לציין שפעולות בזרמים אינן משנות את המקור.

הנה דוגמה מהירה:

ספירה ארוכה = list.stream (). מובחנת (). count ();

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

3.1. מתבשל

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

עבור (מחרוזת מחרוזת: רשימה) {if (string.contains ("a")) {return true; }}

ניתן לשנות קוד זה רק בשורה אחת של קוד Java 8:

isoolist isoolist = list.stream (). anyMatch (element -> element.contains ("a"));

3.2. סִנוּן

ה לְסַנֵן() השיטה מאפשרת לנו לבחור זרם של אלמנטים העונים על פרדיקט.

לדוגמה, שקול את הרשימה הבאה:

רשימת ArrayList = ArrayList חדש (); list.add ("אחד"); list.add ("OneAndOnly"); list.add ("דרק"); list.add ("שינוי"); list.add ("מפעל"); list.add ("justBefore"); list.add ("איטליה"); list.add ("איטליה"); list.add ("יום חמישי"); list.add (""); list.add ("");

הקוד הבא יוצר a זרם של ה רשימה, מוצא את כל האלמנטים של זרם זה המכילים char "d", ויוצר זרם חדש המכיל רק את האלמנטים המסוננים:

זרם זרם = list.stream (). Filter (element -> element.contains ("d"));

3.3. מיפוי

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

רשימת uris = ArrayList חדש (); uris.add ("C: \ My.txt"); זרם זרם = uris.stream (). מפה (uri -> Paths.get (uri));

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

אם יש לך זרם שבו כל אלמנט מכיל רצף של אלמנטים משלו ואתה רוצה ליצור זרם של אלמנטים פנימיים אלה, עליך להשתמש ב flatMap () שיטה:

פרטי רשימה = ArrayList חדש (); details.add (פרט חדש ()); זרם זרם = details.stream (). FlatMap (detail -> detail.getParts (). Stream ());

בדוגמה זו, יש לנו רשימה של אלמנטים מסוג פרט. ה פרט הכיתה מכילה שדה חלקים, שהוא א רשימה. בעזרת ה- flatMap () שיטה, כל אלמנט מהשדה חלקים יחולץ ויתווסף לזרם החדש שהתקבל. אחרי זה, הראשוני זרם יעלם.

3.4. תוֹאֵם

ממשק API של זרם נותן מערכת מכשירים שימושית לאימות אלמנטים ברצף על פי פרדיקט כלשהו. לשם כך, ניתן להשתמש באחת מהשיטות הבאות: anyMatch (), allMatch (), noneMatch (). שמותיהם מסבירים את עצמם. אלה פעולות סופניות שמחזירות א בוליאני:

isValid = בוליאני = list.stream (). anyMatch (אלמנט -> element.contains ("h")); // אמת בוליאני isValidOne = list.stream (). allMatch (אלמנט -> element.contains ("h")); // שווא בוליאני isValidTwo = list.stream (). noneMatch (אלמנט -> element.contains ("h")); // שקר

עבור זרמים ריקים, allMatch () שיטה עם כל פרדיקט נתון תחזור נָכוֹן:

Stream.empty (). AllMatch (אובייקטים :: nonNull); // נכון

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

באופן דומה, ה anyMatch () השיטה תמיד חוזרת שֶׁקֶר לזרמים ריקים:

Stream.empty (). AnyMatch (אובייקטים :: nonNull); // שקר

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

3.5. צִמצוּם

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

דמיין שיש לך רשימה ואתה רוצה לקבל סכום של כל האלמנטים האלה וחלקם ראשוניים מספר שלם (בדוגמה זו 23). אז אתה יכול להפעיל את הקוד הבא והתוצאה תהיה 26 (23 + 1 + 1 + 1).

רשימת מספרים שלמים = Arrays.asList (1, 1, 1); מספר שלם מופחת = מספרים שלמים. זרם (). הפחת (23, (a, b) -> a + b);

3.6. אוספים

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

רשימה resultList = list.stream (). מפה (אלמנט -> element.toUpperCase ()). Collect (Collectors.toList ());

קוד זה משתמש במסוף לאסוף() פעולה לצמצום א זרם אל ה רשימה.

4. מסקנות

במאמר זה נגענו בקצרה בזרמי ג'אווה - בהחלט אחת התכונות המעניינות ביותר ב- Java 8.

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

קוד המקור שמלווה את המאמר זמין באתר GitHub.


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