تحافظ قائمة ArrayList الأساسية على صفيف ديناميكي ، وكل مثيل ArrayList له سعة. تشير هذه السعة إلى حجم الصفيف المستخدم لتخزين عناصر القائمة. هو دائما على الأقل يساوي حجم القائمة. مع إضافة العناصر باستمرار إلى قائمة ArrayList ، تزداد قدرتها أيضًا تلقائيًا.
ArrayList ليس متزامنًا (أي ، وليس آمنًا لخيط). إذا وصلت مؤشرات الترابط المتعددة إلى مثيل ArrayList في نفس الوقت ، وعلى الأقل واحدة من مؤشرات الترابط تعديل القائمة بشكل هيكلي ، يجب أن تحافظ على المزامنة الخارجية. في بيئة متعددة الخيوط ، يمكن الإعلان عن قائمة Arraylist الآمنة في مؤشر الترابط باستخدام طريقة SynchronizedList ، على سبيل المثال:
قائمة ArrayList = collections.synchronizedList (new ArrayList ()) ؛
فيما يلي رمز المصدر لـ ArrayList لتحليل مبدأها.
1. طريقة بناء ArrayList: يوفر ArrayList ثلاث طرق بناء مختلفة
1) ArrayList () ، قم ببناء قائمة فارغة بسعة أولية قدرها 10.
2) ArrayList (int initialcapacity) ، بناء قائمة فارغة مع سعة أولية محددة.
3) ArrayList (مجموعة <؟ تمتد e> c) ، تقوم بإنشاء قائمة بالعناصر التي تحتوي على المجموعة المحددة ، والتي يتم ترتيبها بالترتيب الذي يعيد به تكرار المجموعة.
رمز المصدر كما يلي:
كائن عابر خاص [] elementData ؛ ArrayList public (int initialCapacity) {super () ؛ إذا (initialCappacity <0) رمي غير alficalaRgumentException ("القدرة غير القانونية:"+ initialCappacity) ؛ this.elementData = كائن جديد [initialCapacity] ؛ // إنشاء مجموعة من نوع الكائن بطول 10} ArrayList () {this (10) ؛ // call arraylist (int i)} <br> <br> ArrayList public (Collection <؟ extends e> c) {elementData = c.toarray () ؛ // إرجاع صفيف يحتوي على جميع العناصر في حجم المجموعة = elementData.Length ؛ // c.TOarray قد (بشكل غير صحيح) لا إرجاع كائن [] (انظر 6260652) if (elementData.getClass ()! = Object []. class) elementData = Arrays.copyof (elementData ، size ، object []. class) ؛ // انسخ الصفيف المحدد وأرجع مجموعة من نوع الكائن الذي يحتوي على نفس العنصر والطول} عند استخدام ArrayList () لإنشاء كائن تجميع بدون معلمات ، يتم استدعاء مُنشئ ArrayList (int initialcapacity) في الأسفل لإنتاج صفيف من نوع الكائن بطول 10. عند استخدام مُنشئ مع معلمات نوع المجموعة ، يتم إنشاء مجموعة من نوع الكائن التي تحتوي على نفس العناصر وطولها في القاع.
2. إضافة الطريقة: يوفر ArrayList طريقتين إضافة لإضافة عناصر
1) إضافة (e e) ، أضف العنصر المحدد إلى نهاية هذه القائمة.
2) إضافة (int index ، e e) ، أدخل العنصر المحدد في الموضع المحدد في هذه القائمة. حرك يمين العنصر حاليًا في هذا الموضع (إن وجد) وجميع العناصر اللاحقة (المفهرسة بواسطة 1) حجم int الخاص ؛
إضافة منطقية عامة (e e) {insureCapacity (size + 1) ؛ // قم بتوسيع سعة الصفيف elementData [size ++] = e ؛ // أضف العنصر E إلى صفيف الكائن بحجم ترجمي ، وتنفيذ Size ++ Return True ؛ } public void add (int index ، e element) {if (index> size || index <0) // إذا تجاوزت مجموعة الصفيف المحددة التي يتم إدراجها سعة الصفيف أو أن الوضع المحدد أقل من 0 ، فالرمي استثناء رمي indexoutofboundSexception ("index:"+index+"، size:" size) ؛ insureCapacity (حجم+1) ؛ // قم بتوسيع نظام سعة الصفيف. // انسخ صفيف من صفيف المصدر المحدد ، وتبدأ النسخة من الموضع المحدد إلى الموضع المحدد لمجموعة الهدف. <br> // elementData --- فهرس صفيف المصدر --- موقف البدء في صفيف المصدر <br> // elementData --- فهرس صفيف الهدف+1 --- بداية موضعها في صفيف الهدف <br> // الحجم-الفهرس --- عدد عناصر الصفيف المراد نسخها elementData [index] = element ؛ // ضع العنصر المراد إضافته في حجم فهرس الصفيف المحدد ++ ؛ } public void insureCapacity (int mincapacity) {modcount ++ ؛ int oldcapacity = elementData.Length ؛ . int newCapacity = (OldCapacity * 3)/2 + 1 ؛ // تحديد سعة المصفوفة الجديدة ، والتي تبلغ 1.5 ضعف سعة الصفيف الأصلي +1 إذا (newCapacity <mincapacity) newCapacity = minCapacity ؛ // عادة ما تكون Mincapacity قريبة من الحجم ، لذلك هذا هو الفوز: elementData = Arrays.copyof (ElementData ، NewCapacity) ؛ // انسخ الصفيف المحدد وأرجع سعة المصفوفة الجديدة باعتبارها newCapacity}} إذا تمت إضافة أكثر من 10 عناصر في المجموعة ، فستقوم طبقة ArrayList Bottom بإنشاء صفيف جديد بطول 1.5 مرة + 1 من الصفيف الأصلي ، ونسخ العناصر الموجودة في الصفيف الأصلي إلى الصفيف الجديد ، وسيتم وضع العناصر المضافة اللاحقة في الصفيف الجديد. تتكرر هذه العملية عندما لا يمكن لطول الصفيف الجديد استيعاب العناصر المضافة حديثًا. هذا هو مبدأ التنفيذ لإضافة عناصر إلى مجموعة.
3. احصل على الطريقة:
1) الحصول على (int index) ، إرجاع العنصر في الموضع المحدد في هذه القائمة.
public e get (int index) {rangecheck (index) ؛ // تحقق مما إذا كان الفهرس المحدد الذي تم تمريره هو الإرجاع القانوني (e) elementData [index] ؛ // إرجاع عنصر المصفوفة مع مؤشر Array Corrgcript Index} private void rangecheck (int index) {if (index> = size) // إذا كان المُصنَّف الوارد أكبر من أو يساوي سعة المجموعة ، فأرمي استثناءً رمي indexoutofboundsexception ("فهرس+فهرس+" ، حجم: "+حجم) ؛ } 4. إزالة الطريقة:
1) E قم بإزالة (INT INDEX) ، قم بإزالة العنصر في الموضع المحدد في هذه القائمة. حرك جميع العناصر اللاحقة إلى اليسار (انخفاض مؤشرها بحلول 1).
2) إزالة منطقية (كائن O) ، قم بإزالة العنصر المحدد الذي يظهر لأول مرة في هذه القائمة (إذا كانت موجودة). إذا لم تحتوي القائمة على هذا العنصر ، فلن يتم تغيير القائمة وسيتم إرجاع القيمة المنطقية.
public e remove (int index) {rangecheck (index) ؛ // تحقق مما إذا كان الفهرس المحدد هو ModCount ++ ؛ e oldvalue = (e) elementData [index] ؛ // احصل على عنصر الصفيف في الفهرس المحدد int numMoved = size - index - 1 ؛ // عدد العناصر التي سيتم نقلها إذا (numMove> 0) system.arrayCopy (elementData ، index+1 ، elementData ، index ، numMoved) ؛ // حرك عنصر elementData الصفيف [-الحجم] = فارغ ؛ // دع GC تقوم بعملها على عودة OldValue ؛ } إزالة منطقية عامة (كائن O) {if (o == null) {// إذا كانت المعلمة التي تم تمريرها خالية من (int index = 0 ؛ index <size ؛ index ++) if (elementData [index] == null) {// إزالة الحدوث الأول لـ null fastremove (index) ؛ العودة صحيح. }} else {for (int index = 0 ؛ index <size ؛ index ++) if (o.equals (elementData [index])) {fastremove (index) ؛ العودة صحيح. }} إرجاع خطأ ؛ } private void fastremove (int index) {// قم بإزالة العنصر في الموضع المحدد ، تشبه طريقة التنفيذ إزالة (int i) modcount ++ ؛ int numMoved = size - index - 1 ؛ if (numMoved> 0) system.arrayCopy (elementData ، index+1 ، elementData ، index ، numMoved) ؛ elementData [-size] = null ؛ // دع GC تقوم بعملها} 5. طريقة استنساخ:
1) كائن استنساخ () ، إرجاع نسخة ضحلة من مثيل قائمة ArrayList (لا نسخ هذه العناصر نفسها).
كائن عام clone () {try {ArrayList <e> v = (ArrayList <e>) super.clone () ؛ . // انسخ الصفيف الهدف v.modcount = 0 ؛ العودة v ؛ } catch (clonenotsupportedException e) {// لا ينبغي أن يحدث هذا ، لأننا نرمي internalerror new internalerror () ؛ }} التحليل أعلاه لبعض رموز المصدر الرئيسية لـ ArrayList ، نحن نعرف مبدأ التنفيذ الأساسي لـ ArrayList. هناك النقاط والنقاط التالية لرمز مصدر ArrayList:
1) يتم تنفيذ الطبقة الأساسية من ArrayList بناءً على المصفوفات ، ويمكن العثور على العنصر المستهدف بدقة من خلال المعايير التالية ، وبالتالي فإن كفاءة البحث عالية ؛ ومع ذلك ، فإن إضافة العناصر أو حذفها ستشمل حركة الموضع لعدد كبير من العناصر ، وهو أمر غير فعال.
2) يوفر ArrayList ثلاث طرق بناء مختلفة. تقوم طريقة البناء بدون المعلمة بإنشاء مجموعة من نوع الكائن بطول 10 بشكل افتراضي في الطبقة السفلية. عندما يكون عدد العناصر المضافة في المجموعة أكبر من 10 ، سيتم توسيع الصفيف تلقائيًا ، أي إنشاء صفيف جديد ووضع عناصر الصفيف الأصلي في الصفيف الجديد.
3) توسع طريقة insureCapacity الصفيف ، والتي ستولد صفيفًا جديدًا بطول 1.5 مرة + 1 من الصفيف الأصلي. نظرًا لأن العناصر تضاف باستمرار إلى قائمة ArrayList ، كرر العملية عندما لا يمكن أن تلبي طول الصفيف الاحتياجات.
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.