قرأت جملة من قبل ، وكانت جيدة جدا. سأل أحدهم ما هو استخدام قراءة رمز المصدر؟ تعلم أفكار تصميم الآخرين لتنفيذ وظيفة معينة وتحسين مستوى البرمجة.
نعم ، الجميع ينفذ وظيفة. الأشخاص المختلفين لديهم أفكار تصميم مختلفة. يستخدم بعض الأشخاص 10000 سطر من التعليمات البرمجية ، ويستخدم بعض الأشخاص 5000 سطر. يحتاج بعض الأشخاص إلى تشغيل الكود لعشرات الثواني ، بينما يحتاج الآخرون فقط إلى بضع ثوان. . دعنا نصل إلى الموضوع أدناه.
المحتوى الرئيسي لهذه المقالة:
・تعليق مفصل على تنفيذ ArrayList ، استنادًا إلى JDK 1.8.
・لم يتم شرح جزء المطاردة الفرعية للتكرار بالتفصيل ، وسيتم وضعه في تفسيرات رمز المصدر الأخرى. نحن هنا نركز على تنفيذ ArrayList نفسه.
・لا يتم استخدام التعليقات التوضيحية القياسية ، ويتم تعديل المسافة البادئة للرمز بشكل مناسب لسهولة تقديمها
استيراد java.util.abstractlist ؛ استيراد java.util.arrays ؛ استيراد java.util.bitset ؛ استيراد java.util.collection ؛ استيراد java.util.comparator ؛ استيراد java.util.concurrentModification ؛ java.util.noselementException ؛ استيراد java.util.objects ؛ استيراد java.util.randomaccess ؛ استيراد java.util.spliterator ؛ استيراد java.util.function.consumer ؛ من واجهة القائمة التي يمكن تغيير حجمها. قم بتنفيذ جميع عمليات القائمة الاختيارية والسماح لجميع العناصر ، بما في ذلك NULL ، بتكرارها. * بالإضافة إلى واجهة القائمة ، توفر هذه الفئة طريقة لمعالجة حجم الصفيف لتخزين حجم الصفيف في القائمة. * * تعقيد الوقت: * تعد المكالمات إلى حجم الأساليب ، و isempty ، و Get ، و Set ، و Iderator و ListItiTerator وقتًا ثابتًا. * تعقيد الوقت لإضافة وحذف O (N). جميع العمليات الأخرى هي تعقيد الوقت الخطي. * * السعة: * كل قائمة ArrayList لها سعة ، وحجم السعة هو على الأقل طول عنصر القائمة ، ويمكن تهيئة التهيئة الافتراضية 10. * يمكن زيادة السعة تلقائيًا. * إذا كنت تعرف مقدمًا أن هناك العديد من العناصر في الصفيف ، فيمكنك زيادة السعة مقدمًا من خلال استدعاء طريقة insureCapacity () قبل إضافة عناصر لتقليل النمو الناتج عن النمو التلقائي في الفترة اللاحقة. * يمكن أيضًا تهيئة هذه السعة بواسطة مُنشئ ذي سعة أولية. * * مؤشر الترابط غير آمن: * ArrayList ليس مؤشرًا آمنًا. * إذا كان من الضروري تطبيقه على multithreads ، فيجب إجراء التزامن خارجيًا * * * modcount: * محدد في القائمة التجريدية: محمية عابرة int modcount = 0 ؛ * عدد مرات تعديل هذه القائمة من الناحية الهيكلية. يشير التعديل الهيكلي إلى تغيير حجم القائمة ، أو تعطيل القائمة ، بحيث ينتج التكرار المستمر نتائج غير صحيحة. * يتم استخدام هذا الحقل من قبل تطبيقات Iterator وقائمة Iterator التي يتم إرجاعها بواسطة أساليب Iterator و Listerator. * إذا تم تغيير القيمة في هذا الحقل عن طريق الخطأ ، فإن التكرار (أو القائمة المتكررة) سيلقي نظرة على العمليات التالية أو إزالة أو تعيين أو تعيين أو إضافة عمليات. * عند مواجهة التعديلات المتزامنة أثناء التكرارات ، فإنه يوفر سلوكًا فاشلًا سريعًا بدلاً من السلوك غير المحدد. * ما إذا كانت الفئة الفرعية تستخدم هذا الحقل اختياري. * إذا كانت الفئة الفرعية ترغب في توفير عميل سريع (وسرد القائمة) ، فإنه يضيف ببساطة هذا الحقل إلى إضافة (int ، e) وإزالة الأساليب (وأي طرق أخرى تتجاوزها ، مما يؤدي إلى تعديلات على بنية القائمة). * يجب ألا يتجاوز عدد المكالمات المفردة لإضافة (int ، e) أو إزالة (int) 1 إلى هذا الحقل ، وإلا فإن التكرار (و iterator) سوف يرمي ConcurrentModificationexceptions المزيفة. * إذا كان التنفيذ لا يرغب في توفير عميل سريع الفشل ، فيمكن تجاهل هذا الحقل. * * عابرة: * بشكل افتراضي ، سيتم استمرار جميع متغيرات الأعضاء للكائن. في بعض الحالات ، إذا كنت ترغب في تجنب استمرار بعض متغيرات الأعضاء لكائن ما ، فيمكنك استخدام الكلمة الرئيسية العابرة لوضع علامة عليها ، والتي تعد أيضًا كلمة محفوظة في Java (JDK 1.8) */ArrayList public Class <e> تمتد على قائمة مجردة <e> تنفص <e> ، randomaccess ، java.io.serializable { 8683452581122892189L ؛ // الافتراضية السعة الأولية الثابتة الخاصة int default_capacity = 10 ؛ // تستخدم لمشاركة مثيلات صفيف فارغة مع مثيلات فارغة. الكائن النهائي الثابت الخاص [] فارغ_elementData = {} ؛ . // من أجل اليمين ، يتم تخزين مجموعة العناصر ، وأذونات الوصول إلى الحزمة كائن عابر [] ElementData ؛ // size ، سوف تقوم Java بتهيئة int إلى 0 عند إنشاء حجم int كائن ؛ // قم بتعيين مُنشئ سعة التهيئة بالرقم المحدد ، وسيقوم الرقم السلبي بإلقاء استثناء ArrayList (int initialcapacity) {if (initialCapacity> 0) {this.elementData = new Object [initialCapacity] ؛ } آخر إذا (initialCapacity == 0) {this.elementData = frank_elementData ؛ } آخر {رمي جديد alficalArgumentException ("القدرة غير القانونية:"+initialCapacity) ؛ }} // مُنشئ افتراضي ، استخدم مجموعة التحكم لتهيئة ArrayList () {this.elementData = defaultCapacity_empty_elementData ؛ }. if ((size = elementData.length)! = 0) {// c.tooray may (خطأ) لا إرجاع كائن [] (انظر Java Bug Number 6260652) if (elementData.getClass ()! = object [] } آخر {// استخدم صفيفًا فارغًا this.elementData = فارغ_elementData ؛ }} // لأن السعة غالبًا ما تكون أكبر من العدد الفعلي للعناصر. عندما تكون الذاكرة ضيقة ، يمكنك استدعاء هذه الطريقة لحذف الموقع المحجوز وضبط القدرة على العدد الفعلي للعناصر. // إذا كنت متأكدًا من عدم إضافة أي عناصر ، فيمكنك أيضًا استدعاء هذه الطريقة لتوفير Space Public void trimtosize () {modcount ++ ؛ if (size <elementData.Length) {elementData = (size == 0)؟ فارغ _elementdata: arrays.copyof (elementData ، size) ؛ }} // SET SETTER ARRAY مع معلمات محددة public void insureCapacity (int mincapacity) {// إذا كانت الصفيف فارغة ، فهي مسبق 0 ، وإلا فانتقل إلى القيمة الافتراضية (10) int minexpand = (elementData! = defaultCapity_empty_elementdata)؟ 0: default_capacity ؛ // إذا كانت المعلمة أكبر من سعة الإعداد المسبق ، فاستخدم هذه المعلمة لزيادة تعيين سعة الصفيف إذا (MinCapacity> minexpand) {ضمان capactacity (mincapacity) ؛ }} // عند إضافة عناصر ، تأكد من سعة الصفيف الفراغ الخاص unsureCapacityInternal (int mincapacity) {// استخدم القيمة الافتراضية والمعلمة الأكبر كقيمة مسبقة للسعة if (elementData == DefaultCapacity_Empty_ElementData) {mincapacity = math.max (default_capacity) ؛ } ضمان capticacity (mincapacity) ؛ } // إذا كانت المعلمة أكبر من سعة الصفيف ، فقم بزيادة سعة الصفيف الخاصة التي تضمن cappicpiticacturecapity (int mincapacity) {modcount ++ ؛ if (mincapacity - elementData.Length> 0) تنمو (mincapacity) ؛ } // قد يتسبب الحد الأقصى لسعة الصفيف في تدفق الذاكرة (حد الذاكرة VM) Final static int max_array_size = integer.max_value - 8 ؛ // زيادة القدرة على التأكد من أنه يمكن أن يحتفظ بما لا يقل عن عدد العناصر المحددة بواسطة المعلمة private void تنمو (int mincapacity) {int oldcapacity = elementData.Length ؛ // قم بزيادة سعة الإعداد المسبق بمقدار نصف capacitation = OldCapacity + (OldCapacity >> 1) ؛ // خذ القيمة الأكبر من المعلمة if (newCapacity - minicapacity <0) // أي ، newCapacity <mincapacity newCapacity = minCapacity ؛ // إذا كانت قيمة الإعداد المسبق أكبر من الحد الأقصى الافتراضي ، فتحقق مما إذا كانت تفيض إذا (newCapacity - max_array_size> 0) newCapacity = hugecapacity (mincapacity) ؛ elementData = arrays.copyof (elementData ، newCapacity) ؛ } // تحقق مما إذا كان يفيض. إذا لم يكن هناك تدفق فائض ، فأرجع أقصى قيمة عدد صحيح (int في Java هو 4 بايت ، وبالتالي فإن الحد الأقصى هو 0x7ffffffff) أو القيمة الافتراضية القيمة الافتراضية الثابتة int hugeCapacity (int mincapacity) {if (minicapacity <0) // verflow outofmemorror () ؛ العودة (mincapacity> max_array_size)؟ integer.max_value: max_array_size ؛ } // إرجاع حجم الصفيف العام int () {حجم الإرجاع ؛ } // هل هو فارغ منطقي isempty () {size == 0 ؛ } // ما إذا كان يحتوي على رقم ، فإن إرجاع Bool Public Boolean يحتوي على (كائن O) {return indexof (o)> = 0 ؛ } // إرجاع قيمة في المظهر الأول للمصفوفة ، وسيتم الحكم عليها بطرق مختلفة بناءً على ما إذا كانت فارغة. إذا لم يكن موجودًا ، فإنه يعود -1. التعقيد الزمني هو O (n) public int indexof (object o) {if (o == null) {for (int i = 0 ؛ i <size ؛ i ++) if (elementData [i] == null) return i ؛ } آخر {for (int i = 0 ؛ i <size ؛ i ++) if (o.equals (elementData [i])) return i ؛ } العودة -1 ؛ } // إرجاع قيمة في آخر مرة تظهر فيها في الصفيف. إذا لم يكن موجودًا ، فإنه يعود -1. التعقيد الزمني هو o (n) public int lastIndexof (object o) {if (o == null) {for (int i = size-1 ؛ i> = 0 ؛ i--) if (elementData [i] == null) return i ؛ } آخر {for (int i = size-1 ؛ i> = 0 ؛ i--) if (o.equals (elementData [i])) return i ؛ } العودة -1 ؛ } // إرجاع النسخة ، ولم يتم نسخ العنصر نفسه ، وسيتم طرح استثناء عندما يغير صفيف عملية النسخ كائنات عامة clone () {try {ArrayList <؟> v = (ArrayList <؟>) super.clone () ؛ V.ElementData = arrays.copyof (elementData ، size) ؛ v.modcount = 0 ؛ العودة v ؛ } catch (clonenotsupportedException e) {رمي internalerror new (e) ؛ }} // تحويلها إلى صفيف كائن ، استخدم المصفوفات. }. Arrays.copyof (elementData ، size ، A.GetClass ()) ؛ System.ArrayCopy (elementData ، 0 ، a ، 0 ، size) ؛ if (A.Length> size) a [size] = null ؛ إرجاع أ ؛ } // إرجاع قيمة الموضع المحدد ، لأنها صفيف ، فهي سريعة بشكل خاص suppresswarnings ("غير محدد") e elementData (int index) {return (e) elementData [index] ؛ } // إرجاع قيمة الموضع المحدد ، ولكن تحقق مما إذا كان عدد المواضع يتجاوز طول الصفيف العام E GET (int index) {RangeCheck (index) ؛ إرجاع elementData (الفهرس) ؛ } // قم بتعيين الموضع المحدد على قيمة جديدة وإرجاع القيمة السابقة ، تحقق مما إذا كان هذا الموضع يتجاوز طول المصفوفة العامة (int index ، e element) {rangecheck (index) ؛ e oldvalue = elementData (index) ؛ elementData [index] = element ؛ إرجاع Oldvalue ؛ }. elementData [size ++] = e ؛ العودة صحيح. } // إضافة قيمة في الموضع المحدد وتحقق من الموضع المضافة والسعة الفراغ العام إضافة (int index ، e element) {rangecheckforadd (index) ؛ insureCapacityInternal (حجم + 1) ؛ // public static void arraycopy (Object SRC ، int srcpos ، doubs dest ، int destpos ، int length) // src: source marray ؛ SRCPOS: موضع بدء صفيف المصدر المراد نسخه ؛ القدر: صفيف الوجهة ؛ مصارعة جوار: موضع بداية صفيف الوجهة ؛ الطول: نسخ الطول نظام. elementData [index] = element ؛ حجم ++ ؛ } // حذف قيمة الموضع المحدد ، تحقق من الموضع المضافة وأرجع القيمة السابقة e remove (int index) {rangecheck (index) ؛ modcount ++ ؛ e oldvalue = elementData (index) ؛ int numMoved = size - index - 1 ؛ if (numMoved> 0) system.arrayCopy (elementData ، index+1 ، elementData ، index ، numMoved) ؛ elementData [-size] = null ؛ // من السهل إعادة تدوير فترة جمع القمامة عودة Oldvalue ؛ } // حذف الموقع الذي يظهر فيه العنصر المحدد أولاً عن المنطقية العامة (الكائن O) {if (o == null) {for (int index = 0 ؛ index <size ؛ index ++) if (elementData [index] == null) {fastremove (index) ؛ العودة صحيح. }} else {for (int index = 0 ؛ index <size ؛ index ++) if (o.equals (elementData [index])) {fastremove (index) ؛ العودة صحيح. }} إرجاع خطأ ؛ } // حذف القيمة بسرعة في الموضع المحدد. يجب أن يكون السبب في أن يطلق عليه Fast أنه لا توجد حاجة للتحقق من القيمة وإرجاعها ، لأن الفراغ الخاص فقط fastremove (int index) {modcount ++ ؛ int numMoved = size - index - 1 ؛ if (numMoved> 0) system.arrayCopy (elementData ، index+1 ، elementData ، index ، numMoved) ؛ elementData [-size] = null ؛ // واضح للسماح لـ GC بإجراء عملها} // قم بمسح الصفيف وضبط كل قيمة على NULL لتسهيل جمع القمامة (على عكس إعادة التعيين ، لن يتم إعادة تعيين الحجم الافتراضي للمصفوفة إذا تغيرت) void public clear () {modcount ++ ؛ لـ (int i = 0 ؛ i <size ؛ i ++) elementData [i] = null ؛ الحجم = 0 ؛ } // أضف عنصرًا من مجموعة إلى النهاية ، إذا كانت المجموعة المراد إضافتها فارغة ، فأرجع addall boolean false الكاذبة (مجموعة <؟ تمتد e> c) {object [] a = c.toarray () ؛ int numNew = A.Length ؛ insureCapacityInternal (size + numNew) ؛ System.ArrayCopy (A ، 0 ، ElementData ، size ، numNew) ؛ الحجم += numNew ؛ إرجاع numNew! = 0 ؛ } // الوظيفة هي نفسها كما هو مذكور أعلاه ، إضافة addall boolean العامة (int index ، collection <؟ extends e> c) {rangecheckforadd (index) ؛ Object [] a = c.toarray () ؛ // الصفيف المراد إضافته int numNew = A.Length ؛ // طول المصفوفة المراد إضافتها insureCapacityInternal (Size + numNew) ؛ // ضمان السعة int numMoved = size - index ؛ // الطول الذي لن يتحرك (الجزء السابق) إذا (numMoved> 0) // إذا لم تكن هناك حاجة للتحرك ، فقم بنسخه بنفسه ونقل الجزء الخلفي من الصفيف إلى نظام الموضع الصحيح. System.ArrayCopy (A ، 0 ، ElementData ، index ، numNew) ؛ // أضف صفيفًا جديدًا إلى منتصف حجم الصفيف الأصلي المتغير += numNew ؛ إرجاع numNew! = 0 ؛ } // حذف عنصر النطاق المحدد. المعلمات هي مواقع البداية والإنهاء المحمية المزيل الفراغ (int fromIndex ، int toindex) {modcount ++ ؛ int numMoved = size - toindex ؛ // الطول المحتفظ به نظام القسم الأخير. int newsize = size - (toindex -fromindex) ؛ لـ (int i = newsize ؛ i <size ؛ i ++) {elementData [i] = null ؛ } الحجم = الأخبار ؛ } // تحقق مما إذا كان الرقم يتجاوز طول الصفيف عند إضافة العناصر الخاصة void void rangecheck (int index) {if (index> = size) رمي indexoutofboundsexception (OutofBoundSMSG (index)) ؛ } // تحقق مما إذا كان void private rangecheckforadd (int index) {if (index> size || index <0) رمي indexoutofboundsexception (OutofBoundSMSG (index)) ؛ } // تفاصيل الاستثناء الذي تم إلقاؤه outofboundsmsg (int index)) {return "index:"+index+"، size:"+size ؛ } // حذف عنصر مجموعة Boolean Removeall المحددة (Collection <؟> C) {Objects.Requirenonnull (C) ؛ }. إرجاع batchremove (C ، صحيح) ؛ }/** * تفسير رمز المصدر بواسطة http://anxpp.com/ * param كاملة عندما يكون صحيحًا ، يتم الاحتفاظ بقيمة العنصر في المجموعة المحددة من الصفيف ، وعندما يتم حذف قيمة العنصر في المجموعة المحددة من الصفيف. * return سيتم حذف العناصر المكررة في الصفيف (بدلاً من حذفها مرة واحدة أو عدة مرات) ، وسيعود أي عملية حذف حقيقية */ خاصة batchremove (المجموعة <؟> C ، مكملة منطقية) {Final Object [] elementData = this.ElementData ؛ int r = 0 ، w = 0 ؛ تعديل منطقي = خطأ ؛ جرب {// transweep من خلال الصفيف وتحقق مما إذا كانت هذه المجموعة تحتوي على القيمة المقابلة ، وحرك القيمة المراد الاحتفاظ بها إلى مقدمة الصفيف ، والقيمة الأخيرة من W هي عدد العناصر التي سيتم الاحتفاظ بها // نقطة بسيطة: إذا تم الاحتفاظ بها ، انقل نفس العنصر إلى القسم السابق ؛ إذا تم حذفها ، فانتقل عناصر مختلفة إلى القسم السابق لـ (؛ r <size ؛ r ++) if (c.contains (elementData [r]) == elementData [w ++] = elementData [r] ؛ } أخيرًا {// تأكد من أن الجزء قبل إلقاء الاستثناء يمكنه إكمال العملية المتوقعة ، في حين أن الجزء الذي لم يتم اجتيازه سيتم توصيله بالظهر // r! = الحجم يعني أن الخطأ قد يحدث: c.contains (elementData [r]) يلقي استثناءً (r! = size) W += Size - R ؛ } // إذا كان w == الحجم: يعني أنه يتم الاحتفاظ بجميع العناصر ، لذلك لا توجد عملية حذف ، لذلك سيتم إرجاع خطأ ؛ بخلاف ذلك ، فإن الصفيف والصفيف // عندما يتم إرجاع w! = الحجم ، حتى إذا كانت كتلة المحاولة تطرح استثناء ، فإن العملية قبل التخلص من الاستثناء ، لأن w دائمًا ما يتم الاحتفاظ بالجزء السابق ، ولن يكون الصفيف خارج الترتيب لأن (w! = الحجم) لـ (int i = w ؛ i <size ؛ i ++) elementdata [i] = null ؛ modcount += size - w ؛ // عدد المرات التي تم تغييرها = w ؛ // الحجم الجديد هو عدد العناصر المحفوظة المعدلة = صواب ؛ }} الإرجاع المعدلة ؛ } // حفظ حالة مثيل المصفوفة إلى دفق (أي ، يتم تسلسله). يتم تغيير صفيف عملية الكتابة وسيتم إلقاء استثناء خاص proid writeObject (java.io.ObjectOutputStream S) يرمي java.io.ioException {int expectmodcount = modCount ؛ S.DefaultWriteObject () ؛ // تنفيذ عملية إزالة التسلسل الافتراضية/التسلسل. اكتب الحقول غير المتطايرة وغير المنقولة للفئة الحالية لهذا الدفق // اكتب إلى Size S.WriteInt (الحجم) ؛ // اكتب جميع العناصر من أجل (int i = 0 ؛ i <size ؛ i ++) {S.WriteObject (elementData [i]) ؛ } if (modCount! = electectModCount) {رمي New ConcurrentModificationException () ؛ }} // ما سبق مكتوب ، يتم قراءة هذا. private void readObject (java.io.objectinputstream s) remrows // تنفيذ عملية التسلسل/deserialization الافتراضي s.defaultReadObject () ؛ // اقرأ في طول الصفيف s.readint () ؛ if (size> 0) {insureCapacityInternal (size) ؛ كائن [] a = elementData ؛ // اقرأ في جميع العناصر لـ (int i = 0 ؛ i <size ؛ i ++) {a [i] = s.ReadObject () ؛ }}}} // return listIritorator ، موضع البداية هو المعلمة المحددة public listIritiTorator <e> listIratorator (int index) {if (index <0 || index>) رمي indexoutofboundsexception ("الفهرس:"+الفهرس) ؛ إرجاع New Listitr (index) ؛ } // return listIratorator ، موضع البداية هو 0 قائمة عامة <e> listIratorator () {return new listitr (0) ؛ } // return iterator iterator iterator iterator <e> iterator () {return new itr () ؛ }. // المؤشر ، فهرس العنصر التالي ، التهيئة الافتراضية هي 0 int lastret = -1 ؛ . } // العنصر التالي suppressWarnings ("غير محدد") public e next () {checkforcomodification () ؛ // تحقق مما إذا كان يتم تعديل الصفيف int i = cursor ؛ إذا (i> = size) رمي nosuchelementException () ؛ Object [] elementData = ArrayList.Tis.ElementData ؛ if (i> = elementData.Length) رمي New ConvalrentModificationException () ؛ المؤشر = i + 1 ؛ // حرك المؤشر إلى الوراء (e) elementData [lastret = i] ؛ // قم بتعيين موضع الوصول وإرجاع هذه القيمة} // حذف العنصر public void remove () {if (lastret <0) رمي جديد alficalstateException () ؛ checkforcomodification () ؛ // تحقق مما إذا كان تم تعديل الصفيف {arrayList.Tis.Remove (lastret) ؛ المؤشر = Lastret ؛ lastret = -1 ؛ المتوقع expectModCount = modCount ؛ } catch (indexoutofBoundSexception ex) {رمي New ConcurrentModificationException () ؛ }} OverRideSuppressWarnings ("Unchected") void public foreachRemaining (المستهلك <؟ super e> consumer) {objects.requirenonnull (consumer) ؛ حجم int النهائي = ArrayList.This.size ؛ int i = المؤشر ؛ if (i> = size) {return ؛ } الكائن النهائي [] elementData = ArrayList.This.ElementData ؛ if (i> = elementData.length) {رمي New ConcurrentModificationException () ؛ } بينما (i! = size && modcount == expectedModCount) {consumer.accept ((e) elementData [i ++]) ؛ } المؤشر = i ؛ lastret = i - 1 ؛ checkForComodification () ؛ }. }} // listIritorator iterator يطرف فئة private listitr يمتد ITR erviTerator <e> {listitr (int index) {super () ؛ المؤشر = فهرس ؛ } boolean public hasprevious () {return cursor! = 0 ؛ } public int nextIndex () {return cursor ؛ } public int previousIndex () {return cursor - 1 ؛ } suppressWarnings ("unchected") public e previp () {checkforcomodification () ؛ int i = المؤشر - 1 ؛ إذا (i <0) رمي nosuchelementException () ؛ Object [] elementData = ArrayList.Tis.ElementData ؛ if (i> = elementData.Length) رمي New ConvalrentModificationException () ؛ المؤشر = أنا ؛ إرجاع (e) elementData [lastret = i] ؛ } مجموعة void العامة (e e) {if (lastret <0) رمي جديد alficalstateException () ؛ checkForComodification () ؛ Try {ArrayList.This.set (lastret ، e) ؛ } catch (indexoutofBoundSexception ex) {رمي New ConcurrentModificationException () ؛ }} public void add (e e) {checkforcomodification () ؛ حاول {int i = المؤشر ؛ ArrayList.This.add (i ، e) ؛ المؤشر = i + 1 ؛ lastret = -1 ؛ المتوقع expectModCount = modCount ؛ } catch (indexoutofBoundSexception ex) {رمي New ConcurrentModificationException () ؛ }}} // return subarray من القائمة العامة النطاق المحددة <e> sublist (int fromIndex ، int toindex) {sublistrangecheck (fromIndex ، toindex ، size) ؛ إرجاع المطاردة الفرعية الجديدة (هذا ، 0 ، fromIndex ، Toindex) ؛ }. إذا (toindex> size) رمي indexoutofBoundSexception ("toindex =" + toindex) ؛ إذا كان (fromIndex> toindex) يرمي غير unalfalArgumentException ("fromIndex (" + fromindex + ")> toindex (" + toindex + ")") ؛ }. خاص int int parentoffset ؛ إزاحة int النهائية الخاصة ؛ حجم int Sublist (agrectlist <e> parent ، int indages ، int fromIndex ، int toindex) {this.parent = parent ؛ this.parentoffset = fromIndex ؛ this.offset = إزاحة + fromindex ؛ this.size = toindex - fromIndex ؛ this.modcount = ArrayList.This.ModCount ؛ } مجموعة E العامة (int index ، e e) {rangecheck (index) ؛ checkForComodification () ؛ e oldvalue = arrayList.This.ElementData (إزاحة + فهرس) ؛ ArrayList.This.ElementData [Offset + INDEX] = E ؛ إرجاع Oldvalue ؛ } public e get (int index) {rangecheck (index) ؛ checkForComodification () ؛ return ArrayList.This.ElementData (إزاحة + فهرس) ؛ } public int size () {checkForComodification () ؛ إعادة هذا. } public void add (int index ، e e) {rangecheckforadd (index) ؛ checkForComodification () ؛ parent.add (parentoffset + index ، e) ؛ this.modcount = parent.modcount ؛ this.size ++ ؛ } public e remove (int index) {rangecheck (index) ؛ checkForComodification () ؛ e النتيجة = parent.remove (parentoffset + index) ؛ this.modcount = parent.modcount ؛ this.size-- ؛ نتيجة العودة } Removerange المحمية (int fromIndex ، int toindex) {checkForComodification () ؛ Parent.Removerange (parentoffset + fromindex ، parentoffset + toindex) ؛ this.modcount = parent.modcount ؛ this.size - = toindex - fromindex ؛ } addall boolean public (مجموعة <؟ تمتد e> c) {return addall (this.size ، c) ؛ } addall boolean public (int index ، collection <؟ extends e> c) {rangecheckforadd (index) ؛ int csize = c.size () ؛ إذا كان (csize == 0) إرجاع خطأ ؛ checkForComodification () ؛ parent.addall (parentoffset + index ، c) ؛ this.modcount = parent.modcount ؛ this.size += csize ؛ العودة صحيح. } iTerator العامة <e> iterator () {return listIratorator () ؛ } public listIritator <E> listIratorator (Final int index) {checkforcomodification () ؛ Rangecheckforadd (فهرس) ؛ إزاحة int النهائية = this.offset ؛ إرجاع ListIritiTorator <e> () {int cursor = index ؛ int lastret = -1 ؛ int expectModCount = ArrayList.This.ModCount ؛ boolean public hasnext () {return cursor! = sublist.tis.size ؛ } suppressWarnings ("Unchecked") public e next () {checkForComodification () ؛ int i = المؤشر ؛ if (i> = sublist.this.size) رمي nosuchelementException () ؛ Object [] elementData = ArrayList.Tis.ElementData ؛ إذا (الإزاحة + i> = elementData.Length) رمي ConvintModificationException () ؛ المؤشر = i + 1 ؛ return (e) elementData [Offset + (lastret = i)] ؛ } boolean public hasprevious () {return cursor! = 0 ؛ } suppressWarnings ("unchected") public e previp () {checkforcomodification () ؛ int i = المؤشر - 1 ؛ إذا (i <0) رمي nosuchelementException () ؛ Object [] elementData = ArrayList.Tis.ElementData ؛ إذا (الإزاحة + i> = elementData.Length) رمي ConvintModificationException () ؛ المؤشر = أنا ؛ return (e) elementData [Offset + (lastret = i)] ؛ } suppressWarnings ("غير محدد") public void foreachRemaining (المستهلك <؟ super e> consumer) {objects.requirenonnull (المستهلك) ؛ حجم int النهائي = sublist.This.size ؛ int i = المؤشر ؛ if (i> = size) {return ؛ } الكائن النهائي [] elementData = ArrayList.This.ElementData ؛ if (Offset + i> = elementData.length) {رمي concurrentModificationexception () ؛ } بينما (i! = size && modcount == electectModCount) {consumer.accept ((e) elementData [Offset+(i ++)]) ؛ } // تحديث مرة واحدة في نهاية التكرار لتقليل الكومة الكتابة lastret = المؤشر = i ؛ checkForComodification () ؛ } public int nextIndex () {return cursor ؛ } public int previousIndex () {return cursor - 1 ؛ } public void remove () {if (lastret <0) رمي جديد alficalstateException () ؛ checkForComodification () ؛ جرب {sublist.this.remove (lastret) ؛ المؤشر = Lastret ؛ lastret = -1 ؛ المتوقع expectModCount = ArrayList.This.ModCount ؛ } catch (indexoutofBoundSexception ex) {رمي New ConcurrentModificationException () ؛ }} set public void (e e) {if (lastret <0) refl new alficalstateException () ؛ checkForComodification () ؛ Try {ArrayList.This.set (Offset + Lastret ، E) ؛ } catch (indexoutofBoundSexception ex) {رمي New ConcurrentModificationException () ؛ }} public void add (e e) {checkforcomodification () ؛ جرب {int i = المؤشر ؛ Sublist.This.Add (i ، e) ؛ المؤشر = i + 1 ؛ lastret = -1 ؛ المتوقع expectModCount = ArrayList.This.ModCount ؛ } catch (indexoutofBoundSexception ex) {رمي New ConcurrentModificationException () ؛ }} النهائي checkForComodification () {if (المتوقع! = ArrayList.This.ModCount) رمي concurrentModificationexception () ؛ }} ؛ } القائمة العامة <e> sublist (int fromIndex ، int toindex) {sublistrangecheck (fromIndex ، toindex ، size) ؛ إرجاع المطاردة الفرعية الجديدة (هذا ، إزاحة ، fromindex ، toindex) ؛ } private void rangecheck (int index) {if (index <0 || index> = this.size) رمي indexoutofboundsexception (OutofBoundSMSG (index)) ؛ } private void rangecheckforadd (int index) {if (index <0 || index> this.size) رمي indexoutofboundsexception (outofboundsmsg (index)) ؛ } سلسلة خاصة OutOfBoundSMSG (int index) {return "index:"+index+"، size:"+this.size ؛ } private void checkforcomodification () {if (ArrayList.Tis.ModCount! = this.modcount) رمي concurrentModificationexception () ؛ } spliterator public <e> splitterator () {checkforcomodification () ؛ إرجاع ArrayListsPliterator جديد <e> (ArrayList.This ، الإزاحة ، الإزاحة + this.size ، this.modcount) ؛ }} Override public void foreach (المستهلك <؟ super e> الإجراء) {objects.requirenonnull (Action) ؛ int النهائي المتوقع repittModCount = modCount ؛ suppressWarnings ("غير محدد") النهائي e [] elementData = (e []) this.elementData ؛ حجم int النهائي = this.size ؛ لـ (int i = 0 ؛ modCount == equiredModCount && i <size ؛ i ++) {action.accept (elementData [i]) ؛ } if (modCount! = electectModCount) {رمي New ConcurrentModificationException () ؛ }}/** * ينشئ <em> <a href = "spliterator.html#binding" rel = "خارجي nofollow"> الربط المتأخر </a> </em> * و <em> fail-fast </em> {link spliterator} على العناصر في هذه القائمة *. * * <p> {code spliterator} تقارير {link spliterator#sives} ، * {link spliterator#cursized} ، و {link spliterator#order}. * يجب أن توثق التطبيقات الإفراط في الإبلاغ عن القيم المميزة * الإضافية. * * regurn a {code spliterator} على العناصر في هذه القائمة * since 1.8 */ Override public spliterator <e> splitterator () {return new ArrayListsPliterator <> (this ، 0 ، -1 ، 0) ؛ } /** تقسيم الفهرس القائم على الفهرس ، spliterator تهيئة كسول * /static فئة نهائية arraylistspliterator <e> ينفذ spliterator <e> { / * * * إذا كانت arraylists غير قابلة للتغيير ، أو غير قابلة للتغيير هيكليا (لا * يضيف ، إزاحة ، وما إلى ذلك) ، فيمكننا تنفيذ التكرار الخاص بهم. بدلاً من ذلك ، نكتشف الكثير من التداخل خلال اجتياز العملي دون التضحية بأداء كبير. نعتمد في المقام الأول على * modcounts. هذه ليست مضمونة للكشف عن التزامن * العنف ، وأحيانًا تكون محافظة بشكل مفرط حول * التداخل داخل الخيوط ، ولكن اكتشف ما يكفي من المشكلات ليكون جديراً بالاهتمام في الممارسة العملية. لتنفيذ هذا ، نحن (1) بتكاسل * تهيئة السياج ومتوقعها حتى آخر نقطة نحتاج إلى الالتزام بالدولة التي نتحقق منها * ضد ؛ وبالتالي تحسين الدقة. (لا ينطبق هذا على * المحتملين الفرعيين ، والذين ينشئون التقاطعات ذات القيم الحالية غير الباطنية). (2) نقوم بإجراء فحص واحد فقط * ConcurrentModificationException في نهاية Foreach * (الطريقة الأكثر حساسية للأداء). عند استخدام foreach * (على عكس التكرار) ، يمكننا عادة اكتشاف * التداخل * بعد الإجراءات ، وليس من قبل. مزيد من * فحوصات تفعيل CME تنطبق على جميع أعمال العنف الأخرى الممكنة من الافتراضات على سبيل المثال صفيف elementdata null أو small * بالنظر إلى حجمها () ، والتي لا يمكن أن تحدث إلا بسبب التداخل. هذا يسمح للحلقة الداخلية * لـ Foreach للتشغيل دون أي فحوصات أخرى ، وتبسيط الدقة. على الرغم من أن هذا يستلزم عددًا * من الشيكات ، لاحظ أنه في الحالة المشتركة لـ * list.stream (). foreach (a) ، لا توجد شيكات أو حوسبة أخرى * تحدث في أي مكان آخر غير الداخل. لا يمكن أن تستفيد الأساليب الأخرى التي يتم استخدامها أقل من * هذه * هذه التدفقات. */ قائمة ArrayList النهائية الخاصة <E> ؛ مؤشر int الخاص ؛ // الفهرس الحالي ، تم تعديله على سور int الخاص/تقسيم ؛ // -1 حتى تستخدم ؛ ثم آخر فهرس الماضي Private Int EnterteptModCount ؛ // تهيئة عند مجموعة السياج/ ** إنشاء spliterator جديد يغطي النطاق المعطى*/ arraylistspliterator (ArrayList <e> قائمة ، int inter ، int fence ، int equiredModCount) {this.list = list ؛ // موافق إذا كانت فارغة ما لم تجتاز this.index = Origin ؛ this.fence = السياج ؛ this.ExedModCount = متوقع } private int getFence () {// تهيئة السياج إلى الحجم عند استخدام int hi أولاً ؛ // (يظهر متغير متخصص في الطريقة foreach) ArrayList <e> lst ؛ if ((hi = fence) <0) {if ((lst = list) == null) hi = fence = 0 ؛ else {expectModCount = lst.modcount ؛ مرحبا = السياج = lst.size ؛ }} return hi ؛ } ArrayListsPliterator <e> trysplit () {int hi = getfence () ، lo = index ، mid = (lo + hi) >>> 1 ؛ العودة (lo> = منتصف)؟ NULL: // Divide Range إلى النصف ما لم يكن arraylistspliterator صغير جدًا (LIST ، LO ، index = mid ، electremodcount) ؛ } public boolean tryAdvance(Consumer<? super E> action) { if (action == null) throw new NullPointerException(); int hi = getFence(), i = index; if (i < hi) { index = i + 1; @SuppressWarnings("unchecked") E e = (E)list.elementData[i]; action.accept(e); if (list.modCount != expectedModCount) throw new ConcurrentModificationException(); العودة صحيح. } إرجاع خطأ ؛ } public void forEachRemaining(Consumer<? super E> action) { int i, hi, mc; // hoist accesses and checks from loop ArrayList<E> lst; Object[] a; if (action == null) throw new NullPointerException(); if ((lst = list) != null && (a = lst.elementData) != null) { if ((hi = fence) < 0) { mc = lst.modCount; hi = lst.size; } else mc = expectedModCount; if ((i = index) >= 0 && (index = hi) <= a.length) { for (; i < hi; ++i) { @SuppressWarnings("unchecked") E e = (E) a[i]; action.accept(e); } if (lst.modCount == mc) return; } } throw new ConcurrentModificationException(); } public long estimateSize() { return (long) (getFence() - index); } public int characteristics() { return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED; } } @Override public boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull(filter); // figure out which elements are to be removed // any exception thrown from the filter predicted at this stage // will leave the collection unmodified int removeCount = 0; final BitSet removeSet = new BitSet(size); final int expectedModCount = modCount; final int size = this.size; for (int i=0; modCount == expectedModCount && i < size; i++) { @SuppressWarnings("unchecked") final E element = (E) elementData[i]; if (filter.test(element)) { removeSet.set(i); removeCount++; } } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } // shift surviving elements left over the spaces left by removed elements final boolean anyToRemove = removeCount > 0; if (anyToRemove) { final int newSize = size - removeCount; for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) { i = removeSet.nextClearBit(i); elementData[j] = elementData[i]; } for (int k=newSize; k < size; k++) { elementData[k] = null; // Let gc do its work } this.size = newSize; if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; } return anyToRemove; } @Override @SuppressWarnings("unchecked") public void replaceAll(UnaryOperator<E> operator) { Objects.requireNonNull(operator); final int expectedModCount = modCount; final int size = this.size; for (int i=0; modCount == expectedModCount && i < size; i++) { elementData[i] = operator.apply((E) elementData[i]); } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; } @Override @SuppressWarnings("unchecked") public void sort(Comparator<? super E> c) { final int expectedModCount = modCount; Arrays.sort((E[]) elementData, 0, size, c); if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; }}لخص
The above is all about ArrayList source code analysis in Java programming, and I hope it will be helpful to everyone. يمكن للأصدقاء المهتمين الاستمرار في الرجوع إلى الموضوعات الأخرى ذات الصلة على هذا الموقع. إذا كانت هناك أي أوجه قصور ، فيرجى ترك رسالة لإشارةها. شكرا لك يا أصدقائك لدعمكم لهذا الموقع!