JavaRush /مدونة جافا /Random-AR /فئة ArrayList في جافا

فئة ArrayList في جافا

نشرت في المجموعة
مرحبًا! في المحاضرات السابقة، درسنا بالتفصيل بنية البيانات مثل المصفوفة ونظرنا في الأمثلة الشائعة للعمل معها. لكن بنية البيانات هذه لها عدد من العيوب. كانت الإجابة عليهم في Java هي ظهور ArrayList. لتبسيط الأمر قدر الإمكان، فإن ArrayList في Java عبارة عن مصفوفة "تمت ترقيتها" مع الكثير من الميزات الجديدة.قائمة مصفوفات الفئة - 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='Бегемот'}]
كانت لدينا قائمة تضم قطتين، وأدخلنا واحدة أخرى من خلال الطريقة 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() وتعرض القائمة على الفور بتنسيق سلسلة. في حالة المصفوفات، كان علينا استخدام فئة المصفوفات لهذا الغرض. وبما أننا تذكرنا المصفوفات: في Java، يمكنك بسهولة "التبديل" بين المصفوفة وقائمة 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());
}
من المهم أن نفهم هنا أنه، على عكس lengthخاصية المصفوفة، تقوم طريقة 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
لقد أنشأنا قائمة تحتوي على عنصرين، ولكن عندما احتجنا إليها، تم توسيعها بسهولة. شيء آخر هو أنه إذا أنشأنا في البداية قائمة صغيرة جدًا، فسيتعين عليها إجراء عملية التوسع في كثير من الأحيان، وهذا يستهلك قدرًا معينًا من الموارد. في هذه المحاضرة، بالكاد تطرقنا إلى عملية إزالة العناصر من قائمة ArrayList. وبطبيعة الحال، هذا ليس بسبب النسيان. تم فصل هذا الموضوع إلى محاضرة منفصلة، ​​يمكنك قراءتها أكثر :)
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION