غالبًا ما نستخدم الواجهة التكرارية التي توفرها JDK لتكرار مجموعات Java.
iterator iterator = list.iterator () ؛ بينما (iterator.hasnext ()) {string string = iterator.next () ؛ // افعل شيئًا} يمكن أن يكون التكرار في الواقع ببساطة مفهوما على أنه اجتياز. إنها فئة طريقة توحيد اجتياز جميع الكائنات في حاويات مختلفة. إنه نمط تصميم نموذجي للغاية. نمط التكرار هو طريقة وصول قياسية تستخدم لاجتياز فئات التجميع. يمتلك المنطق الوصول من أنواع مختلفة من فئات التجميع ، وبالتالي تجنب تعريض الهيكل الداخلي للمجموعة إلى العميل. هذه هي الطريقة التي نتعامل بها عندما لا يكون هناك مكرر. على النحو التالي:
بالنسبة للمصفوفات ، نستخدم الاشتراكات للمعالجة:
int [] صفائف = new int [10] ؛ من أجل (int i = 0 ؛ i <lrays.length ؛ i ++) {int a = arrays [i] ؛ // افعل شيئًا} هذه هي الطريقة التي يتم بها التعامل مع ArrayList:
قائمة <Tring> list = new ArrayList <String> () ؛ لـ (int i = 0 ؛ i <list.size () ؛ i ++) {string string = list.get (i) ؛ // افعل شيئًا} لكلا الطريقتين ، نحن نعرف دائمًا مقدمًا الهيكل الداخلي للمجموعة. يتم ربط رمز الوصول والمجموعة نفسها بإحكام ولا يمكنهم فصل منطق الوصول عن فئة المجموعة ورمز العميل. في الوقت نفسه ، تتوافق كل مجموعة مع طريقة اجتياز ، ولا يمكن إعادة استخدام رمز العميل. في التطبيقات العملية ، من المزعج للغاية دمج المجموعتين أعلاه. لذلك من أجل حل المشكلات المذكورة أعلاه ، يكون وضع التكرار شاغراً ، ويستخدم دائمًا نفس المنطق لاجتياز المجموعة. هذا يجعل العميل نفسه غير ضروري للحفاظ على الهيكل الداخلي للمجموعة ، ويتم الحفاظ على جميع الحالات الداخلية من قبل Iterator. لا يتعامل العميل مع فئة التجميع مباشرة. إنه يتحكم دائمًا في التكرار ويرسله "إلى الأمام" ، "للخلف" ، و "أخذ العنصر الحالي" إليه ، ويمكن أن يعبر المجموعة بأكملها بشكل غير مباشر.
ما سبق هو مجرد شرح موجز لنمط التكرار. دعنا نلقي نظرة على واجهة Iterator في Java لنرى كيف تنفذها.
1. java.util.iterator
في Java ، Iterator هي واجهة ، والتي توفر فقط القواعد الأساسية التكرارية. في JDK ، يتم تعريفه على أنه: تكرار يكرر في المجموعة. يحل المتكرر محل التعداد في إطار مجموعات Java. هناك اختلافان بين المتكررين والتعداد:
1. يسمح التكرار للمتصل بإزالة العناصر من المجموعة التي أشار إليها المتكرر أثناء التكرار باستخدام دلالات محددة جيدًا.
2. تم تحسين اسم الطريقة.
تعريف الواجهة كما يلي:
واجهة عامة iterator {boolean hasnext () ؛ الكائن التالي () ؛ void remove () ؛} في:
Object Next (): إرجاع الإشارة إلى العنصر الذي يعبره التكرار فقط. قيمة الإرجاع هي كائن ، والذي يجب إلقاؤه على النوع الذي تحتاجه.
boolean hasnext (): يحدد ما إذا كانت هناك أي عناصر متوفرة في الحاوية للوصول
باطل إزالة (): قم بإزالة العنصر الذي عبره التكرار للتو
بالنسبة لنا ، نحتاج فقط إلى استخدام Next () و hasnext () لإكمال التكرار. على النحو التالي:
لـ (iterator it = c.iterator () ؛ it.hasnext () ؛) {object o = it.next () ؛ // افعل شيئًا} التفسير السابق هو أن Iterator لديه ميزة كبيرة ، أي أننا لسنا بحاجة إلى معرفة النتائج الداخلية للمجموعة. يتم الحفاظ على الهيكل الداخلي وحالة المجموعة من قبل التكرار. نحكم ونحصل على العنصر التالي من خلال الأساليب الموحدة hasnext () و next (). بالنسبة للتنفيذ الداخلي المحدد ، لا داعي للقلق بشأنه. ولكن كمبرمج مؤهل ، من الضروري للغاية معرفة تنفيذ التكرار. يتم تحليل رمز المصدر لـ ArrayList أدناه.
2. تنفيذ Iterator لكل مجموعة
دعنا نحلل تنفيذ Iterator لـ ArrayList. في الواقع ، إذا فهمنا هياكل بيانات ArrayList و Hashset و Treeset وتنفيذها داخليًا ، فسنكون واثقين من كيفية تنفيذ التكرار. نظرًا لأن التنفيذ الداخلي لـ ArrayList يستخدم صفيفًا ، فإننا نحتاج فقط إلى تسجيل فهرس الموضع المقابل ، وتنفيذ طريقته بسيط نسبيًا.
2.1. تنفيذ iterator من ArrayList
داخل ArrayList ، يحدد أولاً ITR من الفئة الداخلية ، والذي ينفذ واجهة التكرار ، على النحو التالي:
الفئة الخاصة ITR تنفذ iterator <e> {// افعل شيئًا} ويتم تنفيذ طريقة iterator () لـ ArrayList:
ITERATOR العام <e> iterator () {return new ITR () ؛} لذا فإن طريقة arraylist.iterator () تُرجع الفصل الداخلي ITR () ، لذا فإن ما نحتاج إلى الاهتمام به الآن هو تنفيذ الفئة الداخلية () ITR ():
يتم تعريف ثلاثة متغيرات من النوع Int داخل ITR: المؤشر ، Lastret ، و EnterteftModCount. حيث يمثل المؤشر موضع الفهرس للعنصر التالي ، ويمثل Lastret موضع الفهرس للعنصر السابق
int المؤشر int lastret = -1 ؛ int equiventModCount = modCount ؛
من تعريفات المؤشر واللاستيت ، يمكن ملاحظة أن Lastret كانت دائمًا أقل من المؤشر ، وبالتالي فإن طريقة تنفيذ HASNEXT () بسيطة للغاية. ما عليك سوى الحكم على ما إذا كان المؤشر و Lastret متساويين.
Boolean Public Hasnext () {Return Cursor! = Size ؛} تنفيذ التالي () بسيط نسبيًا. ما عليك سوى إرجاع العنصر في موضع مؤشر المؤشر ، ثم قم بتعديل المؤشر واللاستيت
public e next () {checkForComodification () ؛ int i = cursor ؛ // سجل فهرس السجل إذا كان (i> = size) // إذا كان العنصر الحصول على أكبر من عدد عناصر التجميع ، فسيتم إلقاء استثناء رمي nosuchelementexception () ؛ Object [] elementData = ArrayList.Tis.ElementData ؛ if (i> = elementData.Length) رمي New ConvalrentModificationException () ؛ cursor = i + 1 ؛ // cursor + 1return (e) elementData [lastret = i] ؛ // lastret + 1 وأرجع العنصر في المؤشر} يستخدم checkforcomodification () بشكل أساسي لتحديد ما إذا كان عدد تعديلات المجموعة قانونية ، أي لتحديد ما إذا كان قد تم تعديل المجموعة أثناء عملية اجتياز. يتم استخدام ModCount لتسجيل عدد تعديلات مجموعة ArrayList ، التي تم تهيئتها إلى 0 ، وكلما تم تعديل المجموعة مرة واحدة (لا يتم احتساب التحديث الداخلي للهيكل) ، مثل الإضافة ، وإزالة الطرق والأساليب الأخرى ، و modcount + 1 ، لذلك إذا ظل ModCount دون تغيير ، فهذا يعني أنه لم يتم تعديل محتوى المجموعة. تستخدم هذه الآلية بشكل أساسي لتنفيذ آلية الفشل السريع لجمع ArrayList. في مجموعات Java ، يكون لجزء كبير من المجموعات آلية فشل سريع. لن أتحدث عنها هنا ، وسأتحدث عنها لاحقًا. لذلك ، لضمان عدم وجود أخطاء أثناء عملية اجتياز ، يجب علينا التأكد من عدم وجود تعديلات هيكلية على المجموعة أثناء عملية اجتياز (باستثناء طريقة إزالة). في حالة حدوث خطأ استثناء ، يجب علينا التحقق بعناية مما إذا كان البرنامج يعاني من خطأ بدلاً من عدم معالجته بعد الصيد.
checkforcomodification النهائي void () {if (modCount! = متوقع reputModCount) رمي ConcurrentModificationexception () ؛} طريقة إزالة () هي تطبيق ، والذي يستدعي طريقة remove () لـ ArrayList نفسها لحذف عنصر موضع Lastret ، ثم تعديل ModCount.
public void remove () {if (lastret <0) رمي جديد alualtStateException () ؛ checkforcomodification () ؛ جرب {arraylist.This.remove (lastret) ؛ cursor = lastret ؛ lastret = -1 ؛ electmodcount = modCount ؛ما ورد أعلاه هو طريقة تنفيذ تكرار مجموعة Java Collection التي قدمها لك المحرر. آمل أن يكون ذلك مفيدًا لك. إذا كان لديك أي أسئلة ، فيرجى ترك رسالة لي وسوف يرد المحرر إليك في الوقت المناسب. شكرا جزيلا لدعمكم لموقع wulin.com!