מערכים בג'אווה: מדריך עזר

1. הקדמה

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

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

  • התחל עם מערכים
  • קרא וכתוב אלמנטים של מערכים
  • דלג על מערך
  • הפוך מערכים לאובייקטים אחרים כמו רשימה אוֹ זרמים
  • מיין, חפש ושלב מערכים

2. מהו מערך?

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

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

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

3. הגדרת מערך

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

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

בואו נלך קודם עם הצהרה ואתחול.

3.1. הַצהָרָה

נתחיל מההכרזה. ישנן שתי דרכים להכריז על מערך ב- Java:

int [] anArray;

אוֹ:

int anOtherArray [];

הראשון נעשה שימוש נרחב יותר מזה האחרון.

3.2. אִתחוּל

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

נתחיל בדרך פשוטה:

int [] anArray = int int [10];

על ידי שימוש בשיטה זו, אנו מאותחלים מערך של עשרה int אלמנטים. שימו לב שעלינו לציין את גודל המערך.

בעת שימוש בשיטה זו, אנו מאותחלים כל אלמנט לערך ברירת המחדל שלו, כאן 0. בעת אתחול מערך של לְהִתְנַגֵד, אלמנטים הם ריק כברירת מחדל.

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

int [] anArray = int int [] {1, 2, 3, 4, 5};

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

4. גישה לאלמנטים

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

לדוגמה, קטע קוד קטן זה ידפיס 10 למסוף:

anArray [0] = 10; System.out.println (anArray [0]);

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

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

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

5. התבוססות על מערך

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

הדרך הראשונה היא להשתמש ב- ל לוּלָאָה:

int [] anArray = int int [] {1, 2, 3, 4, 5}; עבור (int i = 0; i <anArray.length; i ++) {System.out.println (anArray [i]); }

זה אמור להדפיס את המספרים 1 עד 5 למסוף. כפי שאנו רואים עשינו שימוש ב- אורך תכונה. זהו נכס ציבורי המעניק לנו את גודל המערך.

כמובן, ניתן להשתמש במנגנוני לולאה אחרים כגון בזמן אוֹ עושה תוך כדי. אך, באשר לאוספי Java, ניתן לעבור על מערכים באמצעות ה- לכל אחד לוּלָאָה:

int [] anArray = int int [] {1, 2, 3, 4, 5}; עבור (אלמנט int: anArray) {System.out.println (אלמנט); }

דוגמא זו מקבילה לקודמתה, אך נפטרנו מהקוד של boilerplate. ה לכל אחד לולאה היא אפשרות כאשר:

  • אנחנו לא צריכים לשנות את המערך (הכנסת ערך אחר לאלמנט לא תשנה את האלמנט במערך)
  • אנחנו לא צריכים את המדדים כדי לעשות משהו אחר

6. Varargs

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

בטל varargsMethod (מחרוזת ... varargs) {}

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

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

מחרוזת [] anArray = מחרוזת חדשה [] {"חלב", "עגבניה", "צ'יפס"}; varargsMethod (anArray);

יתנהג כמו:

varargsMethod ("חלב", "עגבניה", "צ'יפס");

7. הפיכת מערך לרשימה

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

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

int [] anArray = int int [] {1, 2, 3, 4, 5}; רשימה aList = ArrayList חדש (); עבור (אלמנט int: anArray) {aList.add (element); }

אבל יש דרך אחרת, קצת יותר תמציתית:

מספר שלם [] anArray = מספר שלם חדש [] {1, 2, 3, 4, 5}; רשימה aList = Arrays.asList (anArray);

השיטה הסטטית Arrays.asList לוקח varargs ארגומנט ויוצר רשימה עם הערכים שהועברו. למרבה הצער, לשיטה זו יש כמה חסרונות:

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

8. ממערך לזרם

כעת אנו יכולים להפוך מערכים לרשימות, אך מאז ל- Java 8 יש לנו גישה ל- ממשק API של זרם ואולי נרצה להפוך את המערכים שלנו ל זרם. ג'אווה מספקת לנו את ה- Arrays.stream שיטה לכך:

מחרוזת [] anArray = מחרוזת חדשה [] {"חלב", "עגבניה", "צ'יפס"}; זרם aStream = Arrays.stream (anArray);

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

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

זרם anotherStream = Arrays.stream (anArray, 1, 3);

זה ייצור זרם עם רק "עגבניה" ו"צ'יפס " מיתרים (המדד הראשון כולל ואילו השני בלעדי).

9. מערכי מיון

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

יש עומסי יתר למיון:

  • מערכים מסוג פרימיטיבי: שממוינים בסדר עולה
  • לְהִתְנַגֵד מערכים (אלה לְהִתְנַגֵד חייב ליישם את ניתן להשוות ממשק): שממוינים לפי הסדר הטבעי (בהסתמך על בהשוואה ל שיטה מ ניתן להשוות)
  • מערכים גנריים: שממוינים לפי נתון משווה

בנוסף, ניתן למיין רק חלק ספציפי במערך (העברת מדדי התחלה וסיום לשיטה).

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

בואו נראה איך כל זה עובד דרך כמה דוגמאות:

int [] anArray = int int [] {5, 2, 1, 4, 8}; Arrays.sort (anArray); // anArray הוא כעת {1, 2, 4, 5, 8} שלם [] anotherArray = חדש שלם [] {5, 2, 1, 4, 8}; Arrays.sort (anotherArray); // anotherArray הוא כעת {1, 2, 4, 5, 8} מחרוזת [] yetAnotherArray = מחרוזת חדשה [] {"A", "E", "Z", "B", "C"}; Arrays.sort (yetAnotherArray, 1, 3, Comparator.comparing (String :: toString) .reversed ()); // yetAnotherArray הוא כעת {"A", "Z", "E", "B", "C"}

10. חיפוש במערך

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

int [] anArray = int int [] {5, 2, 1, 4, 8}; עבור (int i = 0; i <anArray.length; i ++) {if (anArray [i] == 4) {System.out.println ("נמצא באינדקס" + i); לשבור; }}

כאן חיפשנו את מספר 4 ומצאנו אותו באינדקס 3.

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

למרבה המזל, ג'אווה מספקת לנו את ה- Arrays.binarySearch שיטה. עלינו לתת לו מערך ואלמנט לחיפוש.

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

בואו נראה דוגמה לשימוש בשיטת החיפוש הבינארי:

int [] anArray = int int [] {1, 2, 3, 4, 5}; אינדקס int = Arrays.binarySearch (anArray, 4); System.out.println ("נמצא באינדקס" + אינדקס);

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

11. שרשור מערכים

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

int [] anArray = int int [] {5, 2, 1, 4, 8}; int [] anotherArray = new int [] {10, 4, 9, 11, 2}; int [] resultArray = int int [anArray.length + anotherArray.length]; עבור (int i = 0; i <resultArray.length; i ++) {resultArray [i] = (i <anArray.length? anArray [i]: anotherArray [i - anArray.length]); }

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

int [] anArray = int int [] {5, 2, 1, 4, 8}; int [] anotherArray = int int [] {10, 4, 9, 11, 2}; int [] resultArray = int int [anArray.length + anotherArray.length]; Arrays.setAll (resultArray, i -> (i <anArray.length? AnArray [i]: anotherArray [i - anArray.length]));

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

הנה אפשרות שלישית להתמזג עם מערכים: System.arraycopy. שיטה זו לוקחת מקור מַעֲרָך, עמדת מקור, יעד מַעֲרָך, מיקום יעד ו int הגדרת מספר האלמנטים להעתקה:

System.arraycopy (anArray, 0, resultArray, 0, anArray.length); System.arraycopy (anotherArray, 0, resultArray, anArray.length, anotherArray.length);

כפי שאנו רואים, אנו מעתיקים את המערך הראשון, ואז את השני (אחרי האלמנט האחרון של הראשון).

12. מסקנה

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

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

הקוד המלא של מאמר זה נמצא ב- GitHub שלנו.