Java Labels

ב־Java, Label (תווית) הוא שם שמצמידים ללולאה או לבלוק קוד, כדי לאפשר לפקודות break ו־continue לפעול על לולאה חיצונית ולא רק על הלולאה הנוכחית.

שימוש ב־Label יכול לחסוך שימוש ב־Flag, למנוע כתיבת מתודות נוספות ולהפוך את הקוד לקצר וברור יותר במקרים מסוימים.

שימוש ב־break עם Label

בדוגמה הבאה ניתן ללולאה החיצונית את השם outer. כאשר j == 3 מתבצע break outer, ולכן כל הלולאות נעצרות מיד.

outer:
for (int i = 0; i < 5; i++) {

    for (int j = 0; j < 5; j++) {

        if (j == 3) {
            break outer;
        }

        System.out.println(i + ", " + j);
    }
}

הפלט:

0, 0
0, 1
0, 2

אם היינו משתמשים ב־break רגיל, היינו יוצאים רק מהלולאה הפנימית, והלולאה החיצונית הייתה ממשיכה לרוץ.

for (int i = 0; i < 5; i++) {

    for (int j = 0; j < 5; j++) {

        if (j == 3) {
            break;
        }

        System.out.println(i + ", " + j);
    }
}

הפלט:

0, 0
0, 1
0, 2
1, 0
1, 1
1, 2
2, 0
2, 1
2, 2
3, 0
3, 1
3, 2
4, 0
4, 1
4, 2

שימוש ב־continue עם Label

הפקודה continue מאפשרת לנו לדלג ישירות לאיטרציה הבאה של לולאה חיצונית.

outer:
for (int i = 0; i < 3; i++) {

    for (int j = 0; j < 3; j++) {

        if (j == 1) {
            continue outer;
        }

        System.out.println(i + ", " + j);
    }
}

הפלט:

0, 0
1, 0
2, 0

כאשר j == 1 הלולאה הפנימית מופסקת, והביצוע קופץ ישירות לאיטרציה הבאה של הלולאה החיצונית.

מתי continue יכול להיות מוחלף ב־break?

במקרים מסוימים ניתן לקבל את אותה התוצאה גם באמצעות break רגיל.

for (int i = 0; i < 3; i++) {

    for (int j = 0; j < 3; j++) {

        if (j == 1) {
            break;
        }

        System.out.println(i + ", " + j);
    }
}

הפלט:

0, 0
1, 0
2, 0

אז למה בכלל להשתמש ב־Label?

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

נניח שקיימת המטריצה הבאה ואנחנו מחפשים את הערך 5:

int[][] matrix = {
    {1,2,3},
    {4,5,6},
    {7,8,9}
};

באמצעות Label ניתן לצאת מיד מכל הלולאות ברגע שהערך נמצא:

search:
for (int i = 0; i < matrix.length; i++) {

    for (int j = 0; j < matrix[i].length; j++) {

        if (matrix[i][j] == 5) {
            break search;
        }
    }
}

פתרון ללא Label

ללא Label נצטרך להשתמש במשתנה עזר (Flag):

boolean found = false;

for (int i = 0; i < matrix.length; i++) {

    for (int j = 0; j < matrix[i].length; j++) {

        if (matrix[i][j] == 5) {
            found = true;
            break;
        }
    }

    if (found) {
        break;
    }
}

דוגמה עם מספר לולאות מקוננות

outer:
for (...) {

    for (...) {

        for (...) {

            if (condition) {
                break outer;
            }
        }
    }
}

ללא Label נצטרך לבצע בדיקות חוזרות באמצעות משתנה עזר:

for (...) {

    for (...) {

        for (...) {

            if (condition) {
                stop = true;
                break;
            }
        }

        if (stop)
            break;
    }

    if (stop)
        break;
}

מתי לא להשתמש ב־Label?

אם קיימת דרך פשוטה וברורה יותר לפתור את הבעיה, עדיף להשתמש בה.

לדוגמה, כאן return הרבה יותר פשוט וברור:

public boolean contains(int[][] arr, int target) {

    for (int[] row : arr) {

        for (int num : row) {

            if (num == target) {
                return true;
            }
        }
    }

    return false;
}

שימוש ב־Streams במקום Label

במקרים רבים ניתן להשתמש ב־Streams בצורה קריאה ופשוטה יותר.

במקום:

boolean found = false;

outer:
for (Integer x : list) {

    if (x > 100) {
        found = true;
        break outer;
    }
}

System.out.println(found);

נכתוב:

boolean found =
    list.stream()
        .anyMatch(x -> x > 100);

חלופות ל־Label

כלל אצבע

השתמשו ב־Label כאשר:

הימנעו מ־Label כאשר:



🏠 Back to Orly's Code Corner