JavaRush /בלוג Java /Random-HE /מחלקה ArrayList ב-Java

מחלקה ArrayList ב-Java

פורסם בקבוצה
שלום! בהרצאות קודמות בדקנו בפירוט מבנה נתונים כזה כמערך ובדקנו דוגמאות נפוצות לעבודה איתם. אבל למבנה הנתונים הזה יש מספר חסרונות. התשובה להם בג'אווה הייתה ההופעה של ArrayList. במילים פשוטות ככל האפשר, ArrayList ב-Java הוא מערך "משודרג" עם הרבה תכונות חדשות.Class ArrayList - 1

במה שונה 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("Hippopotamus");
       cats[2] = new Cat("Philip Markovich");

       cats[1] = null;



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

   @Override
   public String toString() {
       return "Cat{" +
               "name='" + name + '\'' +
               '}';
   }
}
סיכום:

[Cat{name='Томас'}, null, Cat{name='Фorпп Маркович'}]
ניתן לבטל את כל החסרונות הללו באמצעות ArrayList. הוא נוצר בפשטות רבה:
ArrayList<Cat> cats = new ArrayList<Cat>();
כעת יצרנו רשימה לאחסון אובייקטים Cat. שים לב:אנחנו לא מציינים את הגודל של ArrayList מכיוון שהוא ניתן להרחבה אוטומטית. איך זה אפשרי? בְּקַלוּת. תתפלאו, אבל ArrayList מבוסס על מערך רגיל :) כן, בתוכו יש מערך בו מאוחסנים האלמנטים שלנו. אבל ל-ArrayList יש מנגנון מיוחד לעבודה איתו:
  • כאשר מערך פנימי זה מלא, ArrayList יוצר מערך חדש בתוך עצמו. הגודל שלו = (גודל המערך הישן * 1.5) +1.
  • כל הנתונים מועתקים מהמערך הישן למערך החדש
  • המערך הישן מוסר על ידי אספן האשפה.
הודות למנגנון זה, ArrayList (בניגוד למערך) מיישם שיטה להוספת אלמנט חדש. זוהי שיטה add().
public static void main(String[] args) {

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

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

   int thomasIndex = cats.indexOf(thomas);
   System.out.println(thomasIndex);
}
סיכום:

0
זה נכון, האובייקט thomasמאוחסן למעשה בתא 0. למערכים יש לא רק חסרונות, אלא גם יתרונות ללא ספק. אחד מהם הוא חיפוש אלמנט לפי אינדקס. מכיוון שאנו מצביעים על אינדקס, כלומר על כתובת ספציפית בזיכרון, חיפוש מערך כזה מהיר מאוד. ArrayList ב-Java יכול לעשות זאת גם! לשם כך, הוא מיישם שיטה get():
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

   Cat secondCat = cats.get(1);

   System.out.println(secondCat);
}
סיכום:

Cat{name='Бегемот'}
כמו כן, אתה יכול לגלות בקלות אם ArrayList מכיל אובייקט מסוים או לא. זה נעשה באמצעות השיטה contains():
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

   cats.remove(pushok);
   System.out.println(cats.contains(pushok));
}
השיטה בודקת אם האלמנט כלול במערך הפנימי של ArrayList, ומחזירה את התוצאה בצורה boolean- trueאו false. סיכום:

false
ועוד דבר חשוב לגבי ההכנסה. ArrayList מאפשר לך להוסיף נתונים לא רק בסוף המערך, אלא גם לכל תא לפי אינדקס. יש לו שתי שיטות לכך:
  • add(int index, Cat element)
  • 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("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

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

   cats.set(0, philipp);//Now we have a list of 2 cats. We add the 3rd via set:

   System.out.println(cats.toString());
}
סיכום:

[[Cat{name='Томас'}, Cat{name='Бегемот'}]
[Cat{name='Фorпп Маркович'}, Cat{name='Бегемот'}]
הייתה לנו רשימה של 2 חתולים, הכנסנו עוד אחד דרך השיטה set()לתא 0. כתוצאה מכך, הערך הישן המאוחסן בתא זה הוחלף בערך חדש.
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

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

   cats.add(0, philipp);//Now we have a list of 2 cats. Add the 3rd via add

   System.out.println(cats.toString());
}
אבל זה add()עבד אחרת. הוא הזיז את כל האלמנטים ימינה ואז כתב את הערך החדש לתוך התא 0. סיכום:

[Cat{name='Томас'}, Cat{name='Бегемот'}]
[Cat{name='Фorпп Маркович'}, Cat{name='Томас'}, Cat{name='Бегемот'}]
כדי לנקות לחלוטין את הרשימה, השתמש בשיטה clear():
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

   cats.clear();

   System.out.println(cats.toString());
}
סיכום:

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

   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   Cat[] catsArray = {thomas, behemoth, philipp, pushok};

   ArrayList<Cat> catsList = new ArrayList<>(Arrays.asList(catsArray));
   System.out.println(catsList);
}
סיכום:

[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Фorпп Маркович'}, Cat{name='Пушок'}]
אתה יכול לעשות את ההפך - לקבל מערך מאובייקט ArrayList. לשם כך, השתמש בשיטת toArray():
public static void main(String[] args) {

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

   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

   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("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

   System.out.println(cats.size());
}
חשוב להבין כאן שבניגוד למאפיין lengtharray, שיטת 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("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

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

   System.out.println(cats.size());
}
פלט מסוף:

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