Saya membaca kalimat sebelumnya, dan itu sangat bagus. Seseorang bertanya apa gunanya kode sumber membaca? Pelajari ide -ide desain orang lain untuk menerapkan fungsi tertentu dan meningkatkan tingkat pemrograman Anda.
Ya, semua orang mengimplementasikan suatu fungsi. Orang yang berbeda memiliki ide desain yang berbeda. Beberapa orang menggunakan 10.000 baris kode, dan beberapa orang menggunakan 5.000 baris. Beberapa orang perlu menjalankan kode selama puluhan detik, sementara yang lain hanya perlu beberapa detik. . Mari kita mulai topik di bawah ini.
Konten utama artikel ini:
・Komentar terperinci tentang implementasi ArrayList, berdasarkan JDK 1.8.
・Bagian sublist iterator belum dijelaskan secara rinci, dan akan ditempatkan dalam interpretasi kode sumber lainnya. Di sini kami fokus pada implementasi ArrayList itu sendiri.
・Tidak ada anotasi standar yang digunakan, dan lekukan kode disesuaikan dengan tepat untuk diperkenalkan dengan mudah
Impor java.util.abstractlist; impor java.util.arrays; impor java.util.bitset; impor java.util.collection; import java.util.comparator; impor java.util.concurrentModificationException; impor java.util.itator; impor java.utlist; Import Java.Uport. java.util.nosuchelementException; impor java.util.objects; impor java.util.randomaccess; impor java.util.spliterator; impor java.util.function. Daftar antarmuka yang dapat diubah ukurannya. Menerapkan semua operasi daftar opsional dan memungkinkan semua elemen, termasuk NULL, dapat diulang. * Selain antarmuka daftar, kelas ini menyediakan cara untuk memanipulasi ukuran array untuk menyimpan ukuran array dalam daftar. * * Kompleksitas Waktu: * Panggilan ke ukuran metode, isempty, get, atur, iterator dan listiterator adalah waktu yang konstan. * Kompleksitas waktu menambahkan dan menghapus adalah O (n). Semua operasi lainnya adalah kompleksitas waktu linier. * * Kapasitas: * Setiap arraylist memiliki kapasitas, dan ukuran kapasitas setidaknya panjang elemen daftar, dan inisialisasi default adalah 10. * Kapasitas dapat secara otomatis ditingkatkan. * Jika Anda tahu sebelumnya bahwa ada banyak elemen dalam array, Anda dapat meningkatkan kapasitas terlebih dahulu dengan memanggil metode EnsureCapacity () sebelum menambahkan elemen untuk mengurangi overhead pertumbuhan kapasitas otomatis di periode selanjutnya. * Kapasitas ini juga dapat diinisialisasi dengan konstruktor dengan kapasitas awal. * * Thread tidak aman: * Daftar array tidak aman. * Jika perlu diterapkan pada multithreads, sinkronisasi perlu dilakukan secara eksternal * * modcount: * didefinisikan dalam AbstractList: transient intrasi yang dilindungi ModCount = 0; * Berapa kali daftar ini telah dimodifikasi secara struktural. Modifikasi struktural mengacu pada mengubah ukuran daftar, atau mengganggu daftar, sehingga iterasi yang sedang berlangsung menghasilkan hasil yang salah. * Bidang ini digunakan oleh Iterator dan daftar Implementasi Iterator yang dikembalikan oleh metode Iterator dan Listerator. * Jika nilai dalam bidang ini secara tidak sengaja diubah, iterator (atau daftar iterator) akan melempar ConcurrentModificationException sebagai tanggapan terhadap Operasi Berikutnya, Hapus, Atur, atau Tambahkan Operasi. * Ketika dihadapkan dengan modifikasi bersamaan selama iterasi, ia memberikan perilaku yang gagal cepat daripada perilaku non-deterministik. * Apakah subclass menggunakan bidang ini adalah opsional. * Jika subclass ingin memberikan iterator gagal yang cepat (dan daftar iterator), itu cukup menambahkan bidang ini ke metode add (int, e) dan hapus (int) (dan metode lain yang ditimpa, menghasilkan modifikasi pada struktur daftar). * Jumlah panggilan tunggal yang akan ditambahkan (int, e) atau menghapus (int) tidak boleh melebihi 1 ke bidang ini, jika tidak, iterator (dan daftar iterator) akan melempar ConcurrentModificationExceptions palsu. * Jika suatu implementasi tidak ingin memberikan iterator gagal cepat, bidang ini dapat diabaikan. * * Transient: * Secara default, semua variabel anggota suatu objek akan bertahan. Dalam beberapa kasus, jika Anda ingin menghindari bertahan beberapa variabel anggota dari suatu objek, Anda dapat menggunakan kata kunci sementara untuk menandai mereka, yang juga merupakan kata yang dipesan dalam java (JDK 1.8) */ArrayList kelas publik <e> memperluas Daftar Abstrak <e> mengimplementasikan Daftar <E>, ACACKACCESS, pemasangan yang dapat diklonasi, Java.io.serializable (stible -stibersion (stible = java.io. 8683452581122892189L; // kapasitas awal default private static final int default_capacity = 10; // Digunakan untuk berbagi instance array kosong dengan instance kosong. Private Static Final Object [] kosong_elementData = {}; // default array kosong objek akhir statis privat [] defaultcapacity_empty_elementdata = {}; // Untuk kanan, array elemen, izin akses paket disimpan objek transien transien [] elementData; // ukuran, java akan menginisialisasi int ke 0 saat membuat objek ukuran int pribadi; // Atur konstruktor kapasitas inisialisasi dengan nomor yang ditentukan, dan angka negatif akan melempar arraylist publik pengecualian (int initialcapacity) {if (initialcapacity> 0) {this.elementData = objek baru [initialcapacity]; } else if (initialcapacity == 0) {this.elementData = empleme_elementData; } else {lempar new ilegalArgumentException ("Kapasitas ilegal:"+InitialCapacity); }} // Konstruktor default, gunakan array kontrol untuk menginisialisasi arraylist publik () {this.elementData = defaultCapacity_empty_elementData; } // Bangun daftar yang berisi elemen -elemen dalam koleksi dalam urutan pengembalian iterator dari koleksi arraylist publik (koleksi <? Extends e> c) {elementData = c.toArray (); if ((size = elementData.length)! = 0) {// c.toarray may (error) tidak mengembalikan objek [] (lihat Java Bug Number 6260652) if (elementData.getClass ()! = Object []. Class) ElementData = arrays.copyof (ElementData, size, size, class). } else {// gunakan array kosong this.elementData = empleme_elementData; }} // Karena kapasitasnya seringkali lebih besar dari jumlah elemen yang sebenarnya. Saat memori ketat, Anda dapat memanggil metode ini untuk menghapus lokasi yang dipesan dan menyesuaikan kapasitas dengan jumlah elemen yang sebenarnya. // Jika Anda yakin tidak ada elemen yang akan ditambahkan, Anda juga dapat memanggil metode ini untuk menghemat ruang public void trimtosize () {ModCount ++; if (size <elementData.length) {elementData = (size == 0)? Kosong_elementdata: arrays.copyof (elementData, size); }} // Tetapkan kapasitas array dengan parameter tertentu void public EnsureCapacity (int MinCapacity) {// Jika array kosong, prefetch 0, jika tidak, buka nilai default (10) int minexpand = (elementData! = Defaultcapacity_empty_elementdata)? 0: default_capacity; // Jika parameter lebih besar dari kapasitas preset, gunakan parameter ini untuk mengatur lebih lanjut kapasitas array IF (MINCAPACILCITY> MINEXPAND) {SESSUREEEXPLICICECCAPACILE (MINCAPASICITY); } } //When adding elements, ensure the array capacity private void ensureCapacityInternal(int minCapacity) { //Use the default value and the larger parameter as the capacity preset value if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity (MinCapacity); } // Jika parameter lebih besar dari kapasitas array, tingkatkan kapasitas array void swasta ensureeexplicitCapacity (int minCapacity) {modcount ++; if (MINCAPASICATION - ELEMENTDATA.Length> 0) Grow (MinCapacity); } // Kapasitas maksimum array dapat menyebabkan memori overflow (batas memori VM) private static final int max_array_size = integer.max_value - 8; // Tingkatkan kapasitas untuk memastikan bahwa ia dapat menahan setidaknya jumlah elemen yang ditentukan oleh parameter private void Grow (int mincapacity) {int oldcapacity = elementData.length; // Tingkatkan kapasitas preset dengan setengah int newcapacity = oldcapacity + (oldcapacity >> 1); // Ambil nilai yang lebih besar dari parameter jika (newcapacity - MinCapacity <0) // yaitu, newcapacity <mincapacity newcapacity = minsapacity; // Jika nilai preset lebih besar dari maksimum default, periksa apakah itu meluap jika (newcapacity - max_array_size> 0) newcapacity = hugeCapacity (mincapacity); elementData = arrays.copyof (elementData, newcapacity); } // Periksa apakah itu meluap. Jika tidak ada overflow, kembalikan nilai integer maksimum (int di java adalah 4 byte, sehingga maksimum adalah 0x7ffffffff) atau nilai maksimum default private static int hugeCapacity (int mincapacity) {if (mincapacity <0) // lemparan outofmemoryerror baru (); return (Mincapacity> max_array_size)? Integer.max_value: max_array_size; } // kembalikan ukuran array ukuran int publik () {ukuran pengembalian; } // apakah itu kosong boolean public isempty () {return size == 0; } // Apakah itu berisi angka, return bool public boolean berisi (objek o) {return indexof (o)> = 0; } // Kembalikan nilai pada penampilan pertama array, dan itu akan dinilai dengan cara yang berbeda berdasarkan apakah itu nol. Jika tidak ada, ia mengembalikan -1. Kompleksitas waktu adalah o (n) indext int publik (objek o) {if (o == null) {for (int i = 0; i <size; i ++) if (elementData [i] == null) return i; } else {for (int i = 0; i <size; i ++) if (o.equals (elementData [i])) return i; } return -1; } // mengembalikan nilai pada terakhir kali ketika muncul di array. Jika tidak ada, ia mengembalikan -1. Kompleksitas waktu adalah o (n) int lastIndexof publik (objek o) {if (o == null) {for (int i = size-1; i> = 0; i--) if (elementData [i] == null) return i; } else {for (int i = size-1; i> = 0; i--) if (o.equals (elementData [i])) return i; } return -1; } // Kembalikan salinannya, elemen itu sendiri belum disalin, dan pengecualian akan dilemparkan ketika array proses penyalinan mengubah clone objek publik () {coba {arraylist <?> V = (arraylist <?>) Super.clone (); v.elementData = arrays.copyof (elementData, size); v.modcount = 0; mengembalikan v; } catch (clonenotsupportedException e) {lempar internalerror baru (e); }} // Konversi ke array objek, gunakan arrays.copyof () Metode objek publik [] toArray () {return arrays.copyof (elementData, size); } // Mengembalikan array, gunakan runtime untuk menentukan jenisnya, dan array berisi semua elemen dalam daftar ini (dari elemen pertama ke elemen terakhir) // kapasitas array yang dikembalikan ditentukan oleh parameter dan nilai yang lebih besar dalam array @suppresswarnings ("tidak dicatat") PUBLIC <t> T [] TORRAY (t []) {api) {o) {o) {o) {ow fally) {{{api] {{{{{{{t *) {{{{{{t * fally) {n) Arrays.copyof (elementData, size, a.getClass ()); System.ArrayCopy (ElementData, 0, A, 0, ukuran); if (a.length> size) a [size] = null; mengembalikan a; } // Kembalikan nilai posisi yang ditentukan, karena itu adalah array, ini sangat cepat @suppresswarnings ("Unccecked") e elementData (int index) {return (e) elementData [index]; } // Kembalikan nilai posisi yang ditentukan, tetapi periksa apakah jumlah posisi melebihi panjang array public e get (indeks int) {rangeCheck (index); return elementData (indeks); } // Atur posisi yang ditentukan ke nilai baru dan kembalikan nilai sebelumnya, periksa apakah posisi ini melebihi Panjang Array Public E Set (Indeks int, elemen E) {RangeCheck (indeks); E oldValue = elementData (indeks); elementData [index] = elemen; Kembalikan OldValue; } // Tambahkan nilai pertama memastikan kapasitas public boolean add (e e) {ensurecapacityinternal (ukuran + 1); elementData [size ++] = e; Kembali Benar; } // Tambahkan nilai pada posisi yang ditentukan dan periksa posisi yang ditambahkan dan kapasitas public void add (index int, elemen e) {rangeCheckForAdd (index); Ensurecapacityinternal (ukuran + 1); // Public static void arraycopy (objek SRC, int srcpos, objek dest, int destpos, panjang int) // src: array sumber; SRCPOS: Posisi awal dari array sumber yang akan disalin; DEST: Array tujuan; destpos: posisi awal dari array tujuan; Panjang: Copy Length System.ArrayCopy (ElementData, Indeks, ElementData, Indeks + 1, Ukuran - Indeks); elementData [index] = elemen; ukuran ++; } // Hapus nilai posisi yang ditentukan, periksa posisi yang ditambahkan dan kembalikan nilai sebelumnya PUBLIC E REMPANTIVE (INT INDEX) {RangeCheck (index); modcount ++; E oldValue = elementData (indeks); int nummoved = ukuran - indeks - 1; if (nummoved> 0) system.arraycopy (elementData, index+1, elementData, index, nummoved); elementData [-size] = null; // mudah untuk mendaur ulang periode pengumpulan sampah kembali oldValue; } // hapus lokasi di mana elemen yang ditentukan pertama kali muncul boolean publik hapus (objek o) {if (o == null) {for (int index = 0; index <size; index ++) if (elementData [index] == null) {fastremove (index); Kembali Benar; }} else {for (int index = 0; index <size; index ++) if (o.equals (elementData [index])) {fastremove (index); Kembali Benar; }} return false; } // Hapus nilai dengan cepat pada posisi yang ditentukan. Alasan mengapa itu disebut dengan cepat seharusnya karena tidak perlu memeriksa dan mengembalikan nilainya, karena hanya fastremove void pribadi (indeks int) {modcount ++; int nummoved = ukuran - indeks - 1; if (nummoved> 0) system.arraycopy (elementData, index+1, elementData, index, nummoved); elementData [-size] = null; // Bersihkan untuk membiarkan GC melakukan pekerjaannya} // Hapus array dan atur setiap nilai ke nol untuk memfasilitasi pengumpulan sampah (tidak seperti reset, ukuran default array tidak akan diatur ulang jika berubah) void public clear () {modcount ++; untuk (int i = 0; i <size; i ++) elementData [i] = null; ukuran = 0; } // Tambahkan elemen koleksi ke akhir, jika koleksi yang akan ditambahkan kosong, kembalikan false public boolean addall (koleksi <? Extends e> c) {objek [] a = c.toArray (); int numNew = a.length; EnsureCapacityinternal (ukuran + numNew); System.ArrayCopy (A, 0, ElementData, Size, NumNew); ukuran += numnew; kembalikan numnew! = 0; } // Fungsinya sama seperti di atas, tambahkan boolean public addall (index int, collection <? Extends e> c) {rangeCheckForAdd (index); Objek [] a = c.toArray (); // array yang akan ditambahkan int numnew = a.length; // Panjang array yang akan ditambahkan Ensurecapacityinternal (ukuran + numNew); // Pastikan kapasitas int nummoved = size - index; // panjang yang tidak akan bergerak (bagian sebelumnya) jika (nummoved> 0) // jika tidak perlu bergerak, salin dengan sendirinya dan pindahkan bagian belakang array ke sistem posisi yang benar. System.ArrayCopy (A, 0, ElementData, Indeks, NumNew); // Tambahkan array baru ke tengah ukuran array asli yang diubah += numNew; kembalikan numnew! = 0; } // Hapus elemen rentang yang ditentukan. Parameter adalah posisi awal dan akhir yang dilindungi void removerange (int fromIndex, int toindex) {modcount ++; int nummoved = size - toindex; // Panjang yang dipertahankan oleh bagian terakhir System.ArrayCopy (ElementData, Toindex, ElementData, Fromindex, Nummoved); int newsize = size - (toindex -fromindex); untuk (int i = newsize; i <size; i ++) {elementData [i] = null; } size = Newsize; } // Periksa apakah angka tersebut melebihi panjang array saat menambahkan elemen private void rangecheck (int index) {if (index> = size) Lempar indexOutOfBoundSException baru (outofboundsmsg (index)); } // Periksa apakah private void rangeCheckForAdd (int index) {if (index> size || index <0) lempar indexOutofboundsException baru (outofboundsmsg (index)); } // Detail dari String Private Exception Private OutofBoundSMSG (index) {return "index:"+index+", ukuran:"+ukuran; } // hapus elemen koleksi public boolean hapus (koleksi <?> } // Pertahankan hanya elemen -elemen koleksi public boolean retainall (koleksi <?> C) {objeks.requirenonnull (c); return batchremove (c, true); }/** * Interpretasi kode sumber oleh http://anxpp.com/ * @param lengkap ketika benar, nilai elemen dalam koleksi yang ditentukan disimpan dari array, dan ketika false, nilai elemen dalam koleksi yang ditentukan dihapus dari array. * @return elemen duplikat dalam array akan dihapus (bukan hanya dihapus sekali atau beberapa kali), dan operasi penghapusan akan mengembalikan true */ private boolean batchremove (koleksi <?> C, komplemen boolean) {objek akhir [] elementData = this.elementData; int r = 0, w = 0; boolean dimodifikasi = false; Coba {// transweep melalui array dan periksa apakah koleksi ini berisi nilai yang sesuai, pindahkan nilai yang akan dipertahankan ke depan array, dan nilai terakhir W adalah jumlah elemen yang akan dipertahankan // titik sederhana: jika dipertahankan, pindahkan elemen yang sama ke bagian sebelumnya; Jika dihapus, pindahkan elemen yang berbeda ke bagian sebelumnya untuk (; r <size; r ++) if (c.contains (elementData [r]) == komplemen) elementData [w ++] = elementData [r]; } finally {//Make sure that the part before the exception is thrown can complete the expected operation, while the part that has not been traversed will be connected to the back //r!=size means that an error may occur: c.contains(elementData[r]) throws an exception if (r != size) { System.arraycopy(elementData, r,elementData, w,size - r); w += ukuran - r; } // Jika w == ukuran: berarti semua elemen dipertahankan, jadi tidak ada operasi penghapusan, jadi false akan dikembalikan; Kalau tidak, benar dan array // Ketika w! = ukuran dikembalikan, bahkan jika blok percobaan melempar pengecualian, operasi sebelum pengecualian dilemparkan, karena W selalu panjang bagian sebelumnya yang akan dipertahankan, dan array tidak akan rusak karena (w! = ukuran) {untuk (int i = w; i <size; i ++) elementdata [i] = i] {for (int i = w; i <size; i ++) elementdata [i] = i] {for (int i = w; i <size; i ++) elementdata [i] = i] {for (int i = w; i <size; i ++) elementdata [i] = i] {for I = w; i <size; i ++) elementdata [i] = i] {for I = w; i <size; i ++) elementdata [i] = i = i = nulul; modcount += size - w; // berapa kali perubahan ukuran = w; // Ukuran baru adalah jumlah elemen yang diawetkan dimodifikasi = true; }} return dimodifikasi; } // Simpan status instance array ke aliran (yaitu, serial). Array Proses Tulis diubah dan pengecualian akan dilemparkan ke void writeObject (java.io.objectOutputStream s) melempar java.io.ioException {int diharapkanmodcount = modcount; S.DefaultWriteObject (); // Jalankan proses deserialisasi/serialisasi default. Tulis bidang non-statis dan non-transitorium dari kelas saat ini ke aliran ini // Tulis ke ukuran S.Writeint (ukuran); // tulis semua elemen untuk (int i = 0; i <size; i ++) {s.writeObject (elementData [i]); } if (modcount! = diharapkanmodcount) {lempar concurrentModificationException baru (); }} // Di atas ditulis, ini dibaca. private void readObject (java.io.objectInputStream s) melempar java.io.ioException, ClassNotFoundException {elementData = empleme_elementData; // Lakukan proses serialisasi/deserialisasi default s.defaultreadObject (); // Baca dalam panjang array s.readint (); if (size> 0) {ensureCapacityinternal (size); Objek [] a = elementData; // Baca di semua elemen untuk (int i = 0; i <size; i ++) {a [i] = s.readObject (); }}}} // return listiterator, posisi awal adalah parameter yang ditentukan PUBLIK PUBLIKITERATOR <E> LISTERITERATOR (INT INDEX) {if (index <0 || index> size) Lempar indexOutOfBoundSException baru ("index:"+index); return new Listitr (index); } // return listiterator, posisi awal adalah 0 listiterator publik <E> listiterator () {return new listitr (0); } // mengembalikan iterator publik iterator biasa <E> iterator () {return new iTr (); } // Iterator umum mengimplementasikan kelas pribadi ITR mengimplementasikan iterator <E> {int kursor; // Kursor, indeks elemen berikutnya, inisialisasi default adalah 0 int lastret = -1; // Posisi elemen yang diakses terakhir adalah Int diharapkan Modcount = modcount; // Proses iterasi tidak menjalankan array yang dimodifikasi, jika tidak, pengecualian akan dilemparkan // Apakah ada hasnext boolean publik lain () {return kursor! = Size; } // elemen berikutnya @suppresswarnings ("Uncecked") public e next () {checkForComodification (); // Periksa apakah array dimodifikasi int i = kursor; if (i> = size) melempar nosuchelementException baru (); Objek [] elementData = arraylist.this.elementData; if (i> = elementData.length) melempar concurrentmodificationException baru (); kursor = i + 1; // pindahkan kursor mundur kembali (e) elementData [lastret = i]; // Atur posisi akses dan kembalikan nilai ini} // hapus elemen public void remeCE () {if (lastret <0) Lempar baru ilegalstateException (); checkForComodification (); // Periksa apakah array dimodifikasi coba {arraylist.this.remove (lastret); kursor = lastret; lastret = -1; diharapkan modcount = modcount; } catch (IndexOutOfBoundSException ex) {Throw New ConcurrentModificationException (); }} @Override @suppresswarnings ("Uncecked") public void foreachremaining (konsumen <? Super e> konsumen) {objeks.requirenonnull (konsumen); Ukuran int akhir = arraylist.tize.size; int i = kursor; if (i> = size) {return; } objek akhir [] elementData = arraylist.this.elementData; if (i> = elementData.length) {lempar concurrentModificationException baru (); } while (i! = size && ModCount == DiparahmodCount) {Consumer.accept ((e) elementData [i ++]); } kursor = i; lastret = i - 1; checkForComodification (); } // Periksa apakah array dimodifikasi void final checkForComodification () {if (modcount! = Diharapkanmodcount) melempar concurrentModificationException baru (); }} // ListIterator iterator mengimplementasikan kelas private listitr memperluas ITR mengimplementasikan ListIterator <E> {listitr (indeks int) {super (); kursor = indeks; } public boolean hasprevious () {return cursor! = 0; } public int nextIndex () {return kursor; } public int priorIndex () {return kursor - 1; } @SuppressWarnings ("Uncecked") public e sebelumnya () {checkForComodification (); int i = kursor - 1; if (i <0) melempar nosuchelementException baru (); Objek [] elementData = arraylist.this.elementData; if (i> = elementData.length) melempar concurrentmodificationException baru (); kursor = i; return (e) elementData [lastret = i]; } public void set (e e) {if (lastret <0) lempar baru ilegalstateException (); checkForComodification (); coba {arraylist.this.set (lastret, e); } catch (IndexOutOfBoundSException ex) {Throw New ConcurrentModificationException (); }} public void add (e e) {checkForComodification (); coba {int i = kursor; Arraylist.this.add (i, e); kursor = i + 1; lastret = -1; diharapkan modcount = modcount; } catch (IndexOutOfBoundSException ex) {Throw New ConcurrentModificationException (); }}} // Kembalikan subarray dari daftar publik rentang yang ditentukan <e> sublist (int fromIndex, int toindex) {sublistrangecheck (fromIndex, toindex, size); mengembalikan sublist baru (ini, 0, dariindex, toindex); } // Keamanan Periksa statis void sublistrangecheck (int fromIndex, int toindex, int ukuran) {if (fromIndex <0) Lempar indexOutOfBoundsException baru ("fromIndex =" + fromIndex); if (toIndex> size) lempar indexOutofboundsException baru ("toIndex =" + toIndex); if (fromIndex> toIndex) melempar IllegalArgumentException baru ("fromIndex (" + fromIndex + ")> toIndex (" + toindex + ")"); } // Subarray Private Class Sublist Extends AbstractList <E> mengimplementasikan acak ACCHOWAccess {private final abstractList <E> Parent; Private Final Int Parentoffset; Offset int final pribadi; ukuran int; Sublist (AbstractList <E> induk, int offset, int fromIndex, int toindex) {this.parent = parent; this.parentOffset = fromIndex; this.offset = offset + fromIndex; this.size = toindex - fromIndex; this.modcount = arraylist.this.modcount; } public e set (int index, e e) {rangeCheck (index); checkForComodification (); E oldValue = arraylist.this.elementData (offset + index); Arraylist.this.elementData [offset + index] = e; Kembalikan OldValue; } public e get (int index) {rangeCheck (index); checkForComodification (); return arraylist.this.elementData (offset + index); } public int size () {checkForComodification (); kembalikan this.size; } public void add (index int, e e) {rangeCheckForAdd (index); checkForComodification (); Parent.Add (indeks ParentOffset +, E); this.modcount = parent.modcount; this.size ++; } public e Remove (int index) {rangeCheck (index); checkForComodification (); E result = parent.remove (ParentOffset + index); this.modcount = parent.modcount; this.size--; hasil pengembalian; } protected void removerange (int fromIndex, int toIndex) {checkForComodification (); Parent.removerange (ParentOffset + FromIndex, ParentOffset + ToIndex); this.modcount = parent.modcount; this.size - = toindex - fromIndex; } public boolean addall (collection <? extends e> c) {return addall (this.size, c); } public boolean addall (int index, collection <? extends e> c) {rangeCheckForAdd (index); int csize = c.size (); if (csize == 0) return false; checkForComodification (); Parent.addall (indeks ParentOffset +, c); this.modcount = parent.modcount; this.size += csize; Kembali Benar; } public iterator <E> iterator () {return listiterator (); } Public ListIterator <E> listIterator (indeks int akhir) {checkForComodification (); rangecheckforadd (indeks); final int offset = this.offset; return new ListIterator <E> () {int kursor = index; int lastret = -1; int diharapkanmodcount = arraylist.this.modcount; public boolean hasnext () {return cursor! = sublist.this.size; } @Suppresswarnings ("Uncecked") public e next () {checkForComodification (); int i = kursor; if (i> = Sublist.this.size) melempar nosuchelementException baru (); Objek [] elementData = arraylist.this.elementData; if (offset + i> = elementData.length) melempar concurrentModificationException baru (); kursor = i + 1; return (e) elementData [offset + (lastret = i)]; } public boolean hasprevious () {return cursor! = 0; } @SuppressWarnings ("Uncecked") public e sebelumnya () {checkForComodification (); int i = kursor - 1; if (i <0) melempar nosuchelementException baru (); Objek [] elementData = arraylist.this.elementData; if (offset + i> = elementData.length) melempar concurrentModificationException baru (); kursor = i; return (e) elementData [offset + (lastret = i)]; } @Suppresswarnings ("Uncecked") public void foreachremaining (konsumen <? Super e> konsumen) {objeks.requirenonnull (konsumen); Ukuran int akhir = sublist.ini. int i = kursor; if (i> = size) {return; } objek akhir [] elementData = arraylist.this.elementData; if (offset + i> = elementData.length) {lempar concurrentModificationException baru (); } while (i! = size && ModCount == DiplikeModCount) {consumer.accept ((e) elementData [offset+(i ++)]); } // Perbarui sekali di akhir iterasi untuk mengurangi lastret lalu lintas heap = kursor = i; checkForComodification (); } public int nextIndex () {return kursor; } public int priorIndex () {return kursor - 1; } public void remove () {if (lastret <0) Lempar IllegalStateException baru (); checkForComodification (); coba {sublist.this.remove (lastret); kursor = lastret; lastret = -1; diharapkan modcount = arraylist.this.modcount; } catch (IndexOutOfBoundSException ex) {Throw New ConcurrentModificationException (); }} public void set (e e) {if (lastret <0) melempar baru ilegalstateException (); checkForComodification (); coba {arraylist.this.set (offset + lastret, e); } catch (IndexOutOfBoundSException ex) {Throw New ConcurrentModificationException (); }} public void add (e e) {checkForComodification (); coba {int i = kursor; Sublist.this.add (i, e); kursor = i + 1; lastret = -1; diharapkan modcount = arraylist.this.modcount; } catch (IndexOutOfBoundSException ex) {Throw New ConcurrentModificationException (); }} final void checkForComodification () {if (diharapkanmodcount! = arraylist.this.modcount) melempar concurrentModificationException (); }}; } Daftar Publik <E> Sublist (int fromIndex, int toIndex) {Sublistrangecheck (fromIndex, toindex, size); return baru sublist (ini, offset, fromIndex, toindex); } private void rangeCheck (int index) {if (index <0 || index> = this.size) lempar indexOutofboundsException baru (outofboundsmsg (index)); } private void rangeCheckForAdd (int index) {if (index <0 || index> this.size) lempar indexOutofboundsException baru (outofboundsmsg (index)); } private string outofboundsmsg (int index) {return "index:"+index+", size:"+this.size; } private void checkForComodification () {if (arraylist.this.modcount! = this.modcount) lempar concurrentModificationException baru (); } spliterator publik <E> splitterator () {checkForComodification (); kembalikan ArrayListSpliterator baru <E> (arrayList.THIS, Offset, Offset + this.size, this.modcount); }} @Override public void foreach (konsumen <? Super e> tindakan) {objeks.requirenonnull (action); final int diharapkanmodcount = modcount; @Suppresswarnings ("Uncecked") final e [] elementData = (e []) this.elementData; Ukuran int akhir = this.size; untuk (int i = 0; modcount == diharapkanmodcount && i <size; i ++) {action.accept (elementData [i]); } if (modcount! = diharapkanmodcount) {lempar concurrentModificationException baru (); }}/** * Membuat <em> <a href = "spliterator.html#mengikat" rel = "nofollow eksternal"> pengikat akhir </a> </em> * dan <em> gagal-cepat </em> {@link spliterator} di atas elemen dalam daftar * ini. * * <p> {@code spliterator} melaporkan {@link spliterator#berukuran}, * {@link spliterator#subsized}, dan {@link spliterator#ordered}. * Implementasi utama harus mendokumentasikan pelaporan nilai karakteristik * tambahan. * * @return a {@code spliterator} atas elemen dalam daftar ini * @since 1.8 */ @Override Public Spliterator <E> splitterator () {return new ArrayListSpliterator <> (this, 0, -1, 0); } /** splitor spliterator split-by-two yang berbasis indeks, spliterator inisialisasi malas * /statis kelas akhir arraylistspliterator <e> mengimplementasikan spliterator <e> { / * * Jika arraylist tidak dapat diubah, atau tidak dapat diubah secara struktural (no * menambahkan, menghapus, dll), kami dapat mengimplementasikan splitterator mereka * dengan arrayspliter. Sebaliknya kami mendeteksi sebanyak * gangguan selama traversal sebagai praktis tanpa * mengorbankan banyak kinerja. Kami terutama mengandalkan * ModCounts. Ini tidak dijamin untuk mendeteksi kekerasan konkurensi *, dan kadang-kadang terlalu konservatif tentang * gangguan dalam benang, tetapi mendeteksi masalah yang cukup untuk * bermanfaat dalam praktik. Untuk melakukan ini, kami (1) dengan malas * menginisialisasi pagar dan diharapkan MODCount sampai poin * terbaru yang perlu kami komit ke negara yang kami periksa * lawan; dengan demikian meningkatkan presisi. (Ini tidak berlaku untuk * sublists, yang membuat splitterator dengan nilai-nilai * non-lazy saat ini). (2) Kami hanya melakukan pemeriksaan tunggal * ConcurrentModificationException di akhir Foreach * (metode yang paling sensitif terhadap kinerja). Saat menggunakan foreach * (sebagai lawan dari iterator), kami biasanya hanya dapat mendeteksi * gangguan setelah tindakan, bukan sebelumnya. Selanjutnya * Pemeriksaan pemicu CME berlaku untuk semua kemungkinan lain * kekerasan asumsi misalnya null atau terlalu kecil * elementData array mengingat ukurannya (), yang hanya bisa * terjadi karena gangguan. Ini memungkinkan loop dalam * foreach berjalan tanpa pemeriksaan lebih lanjut, dan * menyederhanakan resolusi lambda. Sementara ini memang memerlukan * jumlah cek, perhatikan bahwa dalam kasus umum * list.stream (). Foreach (a), tidak ada cek atau komputasi lain * terjadi di mana saja selain di dalam foreach itu sendiri. Metode lain * yang kurang sering digunakan tidak dapat memanfaatkan sebagian besar * streamlining ini. */ daftar final arraylist <e>; indeks int pribadi; // indeks saat ini, dimodifikasi pada pagar int private advance/split; // -1 sampai digunakan; kemudian satu masa lalu Indeks Private Int Private yang diharapkan MODCOUNT; // diinisialisasi saat pagar set/ ** Buat spliterator baru yang mencakup rentang*/ arrayListSpliterator yang diberikan (daftar arraylist <e>, int asalnya, int pagar, int diharapkanmodcount) {this.list = daftar; // ok jika null kecuali melintasi this.index = asal; this.fence = pagar; this.expectedModCount = diharapkan Modcount; } private int getFence () {// inisialisasi pagar ke ukuran pada pertama gunakan int hai; // (varian khusus muncul dalam metode foreach) Daftar <e> lst; if ((hai = pagar) <0) {if ((lst = daftar) == null) hi = pagar = 0; else {diharapkanmodcount = lst.modcount; hai = pagar = lst.size; }} return hai; } Public ArrayListSpliterator <E> trysplit () {int hi = getFence (), lo = index, mid = (lo + hai) >>> 1; return (lo> = mid)? null: // pembagian rentang menjadi dua kecuali terlalu kecil arraylistspliterator <e> (daftar, lo, index = mid, diharapkan modcount); } 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(); return true; } return false; } 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++; }}Meringkaskan
The above is all about ArrayList source code analysis in Java programming, and I hope it will be helpful to everyone. Teman yang tertarik dapat terus merujuk ke topik terkait lainnya di situs ini. Jika ada kekurangan, silakan tinggalkan pesan untuk menunjukkannya. Terima kasih teman atas dukungan Anda untuk situs ini!