כיצד לגשת לדלפק איטרציה בכל לולאה

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

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

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

במדריך קצר זה, נבחן כמה דרכים ל כל פעולה יכולה לכלול מונה.

2. יישום מונה

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

רשימה IMDB_TOP_MOVIES = Arrays.asList ("גאולת Shawshank", "הסנדק", "הסנדק השני", "האביר האפל");

2.1. ל לוּלָאָה

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

דירוגי רשימות = ArrayList חדש (); עבור (int i = 0; i <films.size (); i ++) {דירוג מחרוזת = (i + 1) + ":" + movies.get (i); rankings.add (דירוג); }

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

assertThat (getRankingsWithForLoop (IMDB_TOP_MOVIES)). מכיל בדיוק ("1: גאולת Shawshank", "2: הסנדק", "3: הסנדק השני", "4: האביר האפל");

עם זאת, לא ניתן לאתר את כל מקורות הנתונים בג'אווה בדרך זו. לִפְעָמִים לקבל היא פעולה אינטנסיבית בזמן, או שאנחנו יכולים רק לעבד את האלמנט הבא של מקור נתונים באמצעות זרם אוֹ ניתן לניתוח.

2.2. ל כל לולאה

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

עבור (סרט מחרוזת: IMDB_TOP_MOVIES) {// השתמש בערך הסרט}

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

int i = 0; עבור (סרט מחרוזת: סרטים) {מחרוזת דירוג = (i + 1) + ":" + סרט; rankings.add (דירוג); i ++; }

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

3. פונקציונלי ל כל אחד

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

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

ממשק ציבורי @FunctionalInterface BiConsumer {void accept (T t, U u); }

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

חלל סטטי forEachWithCounter (מקור ניתן לביצוע, צרכן BiConsumer) {int i = 0; עבור (פריט T: מקור) {consumer.accept (i, item); i ++; }}

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

דירוג רשימות = ArrayList חדש (); forEachWithCounter (סרטים, (i, movie) -> {דירוג מחרוזת = (i + 1) + ":" + movies.get (i); rankings.add (דירוג);});

4. הוספת מונה ל לכל אחד עם זרם

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

ה זרם עבור כל אחד פונקציה לוקח a צרכן לעבד את הפריט הבא. אנחנו יכולים, עם זאת, ליצור את זה צרכן כדי לעקוב אחר הדלפק ולהעביר את הפריט אל BiConsumer:

ציבורי סטטי ציבורי עם מונה (BiConsumer צרכן) {מונה AtomicInteger = חדש AtomicInteger (0); פריט החזרה -> הצרכן. קבלה (counter.getAndIncrement (), פריט); }

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

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

בואו נראה את זה בשימוש על ידי דוגמת דירוג הסרטים שלנו כנגד a זרם שקוראים לו סרטים:

דירוגי רשימות = ArrayList חדש (); movies.forEach (withCounter ((i, movie) -> {דירוג מחרוזת = (i + 1) + ":" + סרט; rankings.add (דירוג);}));

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

5. מסקנה

במאמר קצר זה בדקנו שלוש דרכים להצמיד מונה ל- Java ל כל פעולה.

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

כמו תמיד קוד הדוגמה למאמר זה זמין ב- GitHub.