CodeGym /בלוג Java /Random-HE /Java ArrayList
John Squirrels
רָמָה
San Francisco

Java ArrayList

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

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

  • אין שיטות למחוק פריט. ערך יכול להיות רק "לאפס".
public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public static void main(String[] args) {

       Cat[] cats = new Cat[3];
       cats[0] = new Cat("Thomas");
       cats[1] = new Cat("Behemoth");
       cats[2] = new Cat("Lionel Messi");

       cats[1] = null;



       System.out.println(Arrays.toString(cats));
   }

   @Override
   public String toString() {
       return "Cat{" +
               "name='" + name + '\'' +
               '}';
   }
}
פלט: [Cat{name='Thomas'}, null, Cat{name='Lionel Messi'}] למרבה המזל, היוצרים של Java מודעים היטב ליתרונות ולחסרונות של מערכים, ולכן יצרו מבנה נתונים מעניין מאוד בשם Java ArrayList . אם מדברים בצורה פשוטה ככל האפשר, Java ArrayList הוא מערך "משומם" עם הרבה תכונות חדשות.

כיצד ליצור ArrayList

קל מאוד ליצור:
ArrayList<Cat> cats = new ArrayList<Cat>();
כעת יצרנו רשימה לאחסון חפצי חתול . שים לב שאיננו מציינים את הגודל של ArrayList , מכיוון שהוא יכול להתרחב באופן אוטומטי. איך זה אפשרי? זה די פשוט, למעשה. זה אולי יפתיע אתכם, אבל ArrayList ב-Java בנוי על גבי מערך רגיל מאוד :) כן, הוא מכיל מערך, ושם מאוחסנים האלמנטים שלנו. אבל ל-ArrayList ב-Java יש דרך מיוחדת לעבוד עם המערך הזה:
  • כאשר המערך הפנימי מלא, ArrayList יוצר מערך חדש באופן פנימי. גודל המערך החדש הוא גודל המערך הישן כפול 1.5 פלוס 1.

  • כל הנתונים מועתקים מהמערך הישן למערך החדש

  • המערך הישן מנקה על ידי אספן האשפה.
מנגנון זה מאפשר ל-Java ArrayList (בניגוד למערך רגיל) ליישם שיטה להוספת אלמנטים חדשים. זו add()השיטה
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<Cat>();
   cats.add(new Cat("Behemoth"));
}
פריטים חדשים מתווספים לסוף הרשימה. כעת אין סיכון להציף את המערך, כך ששיטה זו בטוחה לחלוטין. אגב, ArrayList יכול לא רק למצוא אובייקט לפי האינדקס שלו, אלא גם להיפך: הוא יכול להשתמש בהפניה כדי למצוא אינדקס של אובייקט ב- ArrayList ! לשם כך מיועדת שיטת indexOf() : אנו מעבירים הפניה לאובייקט שאנו רוצים, ו- indexOf() מחזיר את האינדקס שלו:
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   int thomasIndex = cats.indexOf(thomas);
   System.out.println(thomasIndex);
}
פלט: 0 זה נכון. אובייקט תומאס שלנו אכן מאוחסן באלמנט 0. למערכים אין רק חסרונות. יש להם גם יתרונות שאין עוררין עליהם. אחד מהם הוא היכולת לחפש אלמנטים לפי אינדקס. מכיוון שאנו מצביעים על אינדקס, כלומר על כתובת זיכרון ספציפית, החיפוש של מערך בצורה זו הוא מהיר מאוד. ArrayListגם יודע איך לעשות את זה! שיטת get() מיישמת את זה:
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   Cat secondCat = cats.get(1);

   System.out.println(secondCat);
}
פלט: Cat{name='Behemoth'} בנוסף, אתה יכול לגלות בקלות אם ArrayList מכיל אובייקט מסוים. זה נעשה באמצעות השיטה ArrayList contains():
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   cats.remove(fluffy);
   System.out.println(cats.contains(fluffy));
}
השיטה בודקת אם המערך הפנימי של ArrayList מכיל את האלמנט, ומחזירה ערך בוליאני (true או false). פלט: false ועוד דבר חשוב לגבי הכנסה. ArrayList מאפשר לך להשתמש באינדקס כדי להוסיף אלמנטים לא רק בסוף המערך, אלא בכל מקום. יש לזה שתי שיטות:
  • ArrayList add(int index, Cat element)
  • ArrayList set (int index, Cat element)
כטיעונים, שתי השיטות הללו לוקחות את האינדקס של המיקום שבו ברצונך להכניס, והתייחסות לאובייקט עצמו. ההבדל הוא שהוספה באמצעות set() מחליפה את הערך הישן. הוספה באמצעות add() תחילה מעביר באחד את כל האלמנטים מ-[index] לסוף המערך, ולאחר מכן מוסיפה את האובייקט שצוין במיקום הריק שנוצר.

הנה דוגמה:

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);

   System.out.println(cats.toString());

   cats.set(0, lionel);// Now we have a list of 2 cats. Adding a 3rd using set

   System.out.println(cats.toString());
}
פלט: [[Cat{name='Thomas'}, Cat{name='Behemoth'}] [Cat{name='Lionel Messi'}, Cat{name='Behemoth'}] הייתה לנו רשימה של 2 חתולים . לאחר מכן הכנסנו עוד אחד כאלמנט 0 בשיטת set() . כתוצאה מכך, האלמנט הישן הוחלף באחד חדש.
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);

   System.out.println(cats.toString());

   cats.add(0, lionel);// Now we have a list of 2 cats. Adding a 3rd using add

   System.out.println(cats.toString());
}
והנה אנו רואים ש- add() עובד אחרת. זה מזיז את כל האלמנטים ימינה ואז כותב את הערך החדש כאלמנט 0. פלט: [Cat{name='Thomas'}, Cat{name='Behemoth'}] [Cat{name='Lionel Messi'}, Cat{name='Thomas'}, Cat{name='Behemoth'}] כדי לנקות את הרשימה לחלוטין, אנו משתמשים בשיטת clear() :
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   cats.clear();

   System.out.println(cats.toString());
}
פלט: [] הכל הוסר מהרשימה. אגב, שימו לב: בניגוד למערכים, ArrayList עוקף את שיטת toString() וכבר מציג את הרשימה כמחרוזות. עם מערכים רגילים, היינו צריכים להשתמש במחלקה Arrays בשביל זה. ומכיוון שהזכרתי Arrays : Java מאפשרת לך בקלות "לעבור" בין מערך ל- ArrayList , כלומר להמיר אחד לשני. למחלקה Arrays יש מתודה Arrays.asList() בשביל זה. אנו משתמשים בו כדי לקבל את התוכן כמערך ולהעביר אותם לבנאי ArrayList שלנו :
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();


   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   Cat[] catsArray = {thomas, behemoth, lionel, fluffy};

   ArrayList<Cat> catsList = new ArrayList<>(Arrays.asList(catsArray));
   System.out.println(catsList);
}
פלט: [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}] אתה יכול גם ללכת בכיוון ההפוך: קבל מערך מאובייקט ArrayList . אנו עושים זאת באמצעות שיטת toArray() :
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();

   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   Cat[] catsArray = cats.toArray(new Cat[0]);

   System.out.println(Arrays.toString(catsArray));
}
הערה: העברנו מערך ריק לשיטת toArray() . זו לא שגיאה. בתוך המחלקה ArrayList , שיטה זו מיושמת בצורה כזו שהעברת מערך ריק מגבירה את הביצועים שלו. רק זכור זאת לעתיד (כמובן, אתה יכול להעביר מערך בגודל מסוים; זה גם יעבוד). אה, בערך הגודל. ניתן למצוא את הגודל הנוכחי של הרשימה באמצעות שיטת size() :
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();


   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   System.out.println(cats.size());
}
חשוב להבין שבניגוד למאפיין האורך של מערך , השיטה ArrayList.size() מחזירה את המספר האמיתי של האלמנטים, לא את הקיבולת המקורית. אחרי הכל, לא ציינו גודל בעת יצירת ה- ArrayList . עם זאת, אתה יכול לציין זאת - ל- ArrayList יש בנאי מתאים. אבל במונחים של הוספת אלמנטים חדשים, זה לא משנה את ההתנהגות שלו:
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>(2);// create an ArrayList with an initial capacity of 2


   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   System.out.println(cats.size());
}
פלט מסוף: 4 יצרנו רשימה של 2 אלמנטים, אבל היא התרחבה בשקט כשהיינו צריכים את זה. שיקול נוסף הוא שאם ניצור רשימה קטנה מאוד בהתחלה, היא תצטרך להתרחב לעתים קרובות יותר, מה שישתמש במשאבים מסוימים. כמעט ולא נגענו בתהליך של הסרת אלמנטים מ- ArrayList בשיעור זה כמובן, זה לא בגלל שזה חמק לנו מהראש. הכנסנו את הנושא הזה לשיעור נפרד שתפגשו מאוחר יותר :) כדי לחזק את מה שלמדת, אנו מציעים לך לצפות בשיעור וידאו מקורס ג'אווה שלנו
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION