Я читал предложение раньше, и это было очень хорошо. Кто -то спросил, в чем используется чтение исходного кода? Изучите идеи дизайна других, чтобы реализовать определенную функцию и улучшить свой уровень программирования.
Да, все реализуют функцию. У разных людей разные дизайнерские идеи. Некоторые люди используют 10 000 строк кода, а некоторые люди используют 5000 строк. Некоторым людям нужно запускать код в течение десятков секунд, в то время как другим нужно всего несколько секунд. Полем Давайте перейдем к теме ниже.
Основное содержание этой статьи:
・Подробный комментарий о реализации ArrayList, основанный на JDK 1.8.
・Часть итератора подсознания не была подробно объяснена и будет размещена в других интерпретациях исходного кода. Здесь мы сосредоточимся на реализации самого ArrayList.
・Стандартные аннотации не используются, и отступление кода регулируется соответствующим образом для удобного введения
Импорт java.util.abstractlist; import java.util.arrays; import java.util.bitset; импорт java.util.collection; импорт java.util.comparator; импорт java.util.concurrentmodificationexception; импорт java.util.iterator; import java.util.listrator java.util.nosuchelementexception; import java.util.objects; import java.util.randomaccess; import java.util.spliterator; импорт java.util.function.consumer; импорт java.util.function.predicate; импорт java.util.function.unaryperator; * * * * Список интерфейса, который может быть изменен. Реализуйте все необязательные операции списка и позволяйте всем элементам, включая NULL, повторять. * В дополнение к интерфейсу списка этот класс предоставляет способ манипулировать размером массива для хранения размера массива в списке. * * Сложность времени: * Призывы к методам размер, iSempty, Get, Set, итератор и ListIterator - это постоянное время. * Сложность времени добавления и удаления составляет O (n). Все остальные операции - это линейная сложность времени. * * Емкость: * Каждый ArrayList имеет емкость, а размер емды составляет как минимум длину элемента списка, а инициализация по умолчанию составляет 10. * емкость может быть автоматически увеличена. * Если вы заранее знаете, что в массиве есть много элементов, вы можете увеличить емкость заранее, позвонив в метод EnceRecapacity (), прежде чем добавить элементы, чтобы уменьшить накладные расходы на рост автоматических мощностей в более поздний период. * Эта емкость также может быть инициализирована конструктором с начальной емкостью. * * Поток небезопасен: * ArrayList не безопасен. * Если это необходимо применить к многопоточным чтению, синхронизация должна быть выполнена извне * * modcount: * определено в AbstractList: Защищенный Transient int modcount = 0; * Количество раз, когда этот список был изменен структурно. Структурная модификация относится к изменению размера списка или нарушением списка, так что продолжающаяся итерация дает неправильные результаты. * Это поле используется в реализациях итератора итератора, возвращаемых методами итератора и листератора. * Если значение в этом поле случайно изменено, итератор (или итератор списка) выбросит coundrentModificationException в ответ на следующее, удалить, предыдущие, установить или добавить операции. * Когда сталкивается с одновременными модификациями во время итераций, он обеспечивает быстрое неудачное поведение, а не неэтерминированное поведение. * Использует ли подкласс это поле необязательным. * Если подкласс желает обеспечить итератор (и итератор (и итератор (и итератор (и итератор (и итератор (и перечислите это поле (int, e, E) и удалите (int) методы (и любые другие методы, которые он переопределяет, что приводит к модификациям в структуре списка). * Количество отдельных вызовов для добавления (int, e) или удаления (int) не должно превышать 1 в этом поле, в противном случае итератор (и итератор списка) будет выбрасывать фальшивые concurrentmodificationExceptions. * Если реализация не хочет предоставлять итератор быстрого сбоя, это поле можно игнорировать. * * Transiet: * По умолчанию все переменные элемента объекта будут сохраняться. In some cases, if you want to avoid persisting some member variables of an object, you can use the transient keyword to tag them, which is also a reserved word in java (JDK 1.8) */public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{ private static final long serialVersionUID = 8683452581122892189L; // Начальная емкость по умолчанию частная статическая конечная окончательная финальная int default_capacity = 10; // используется для обмена экземплярами пустых массивов с пустыми экземплярами. Частный статический конечный объект [] empty_elementData = {}; // по умолчанию пустое массив частного статического конечного объекта [] defaultCapacity_empty_elementData = {}; // для правого массива элементов, разрешения на доступ к пакетам являются хранящимися переходными объектом [] elementData; // размер, Java будет инициализировать int до 0 при создании объекта Private Int Size; // Установите конструктор емкости инициализации с указанным номером, и отрицательное число выбросит исключение Public ArrayList (int initialCapacity) {if (initialCapacity> 0) {this.elementData = new Object [initialCapacity]; } else if (initialCapacity == 0) {this.ElementData = empty_elementData; } else {бросить new allogalargumentException ("Незаконная способность:"+initialCapacity); }} // Конструктор по умолчанию, используйте массив управления для инициализации public arraylist () {this.elementData = defaultCapacity_empty_elementData; } // Создание списка, содержащего элементы в коллекции в порядке возврата итератора, коллекционного Public ArrayList (Collection <? Extends E> C) {elementData = c.ToArray (); if ((size = elementdata.length)! = 0) {// c.toarray может (ошибка) не возвращать объект [] (см. Номер ошибки Java 6260652) if (elementData.getClass ()! = Object []. Class) elementData = arrays.copyof (elementdata, size, object []. Class); } else {// Использовать пустой массив this.elementData = empty_elementData; }} // Потому что емкость часто больше, чем фактическое количество элементов. Когда память плотная, вы можете вызвать этот метод, чтобы удалить зарезервированное местоположение и отрегулировать емкость на фактическое количество элементов. // Если вы уверены, что элементы не будут добавлены, вы также можете вызвать этот метод, чтобы сохранить Space public void trimtosize () {modcount ++; if (size <elementdata.length) {elementData = (size == 0)? Empty_elementdata: arrays.copyof (elementdata, size); }} // Установите емкость массива с указанными параметрами public void evireCapacity (int mincapacity) {// Если массив пуст, предварительно перефетч 0, иначе перейдите к значению по умолчанию (10) int minexpand = (elementdata! = Defaultcapacity_empty_elementdata)? 0: default_capacity; // Если параметр больше, чем предустановленная емкость, используйте этот параметр, чтобы дополнительно установить емкость массива, если (mincapacity> minexpand) {убедитесь, }} // При добавлении элементов убедитесь, что емкость массива Private void evureCapacityInternal (int mincapacity) {// Используйте значение по умолчанию и больший параметр в качестве предварительного значения емкости if (elementData == defaultcapacity_empty_elementData) {minCapacity = math.max (default_capacity, mincapacity); } обеспечить explicitcapacity (mincapacity); } // Если параметр больше, чем емкость массива, увеличьте емкость массива private void uliexplicitcapacity (int mincapacity) {modcount ++; if (mincapacity - elementdata.length> 0) выращивать (mincapacity); } // Максимальная емкость массива может вызвать переполнение памяти (предел памяти VM) частное статическое окончательное окончательное окончательное значение int max_array_size = integer.max_value - 8; // Увеличить способность, чтобы убедиться, что он может удерживать как минимум количество элементов, указанных параметром Private void Grow (int mincapacity) {int oldCapacity = elementData.length; // Увеличить предустановленную емкость на половину int newcapacity = oldCapacity + (OldCapacity >> 1); // взять большее значение из параметра if (newcapacity - mincapacity <0) // то есть, newcapacity <mincapacity newcapacity = mincapacity; // Если предустановленное значение больше, чем максимум по умолчанию, проверьте, переполняется ли оно if (newcapacity - max_array_size> 0) newcapacity = gugecapacity (mincapacity); elementData = arrays.copyof (elementdata, newcapacity); } // Проверьте, переполняется ли он. Если нет переполнения, верните максимальное целочисленное значение (int in java составляет 4 байта, поэтому максимум равен 0x7ffffffff) или максимальное значение по умолчанию частного статического статического int hugecapacity (int mincapacity) {if (mincapacity <0) // переполняет новую Outofmemororror (); return (mincapacity> max_array_size)? Integer.max_value: max_array_size; } // возвращать размер массива public int size () {return size; } // Это пусто публично логический isempty () {return size == 0; } // будь то число, возвращается Bool public boolean содержит (Object 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; } else {for (int i = 0; i <size; i ++) if (o.equals (elementdata [i])) return i; } return -1; } // возвращать значение в последний раз, когда оно появляется в массиве. Если его не существует, он возвращает -1. Сложность времени o (n) public int antindexof (object 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; } // Вернуть копию, сам элемент не был скопирован, и исключение будет добавлено, когда массив процесса копирования изменит public Object Clone () {try {arraylist <?> V = (arraylist <?>) Super.clone (); v.elementData = arrays.copyof (elementdata, size); v.modcount = 0; возврат V; } catch (clonenotsupportedException e) {бросить новый InternalError (e); }} // конвертировать в массив объектов, используйте метод Arrays.copyof () public object [] toarray () {return arrays.copyof (elementdata, size); } // Верните массив, используйте время выполнения, чтобы определить тип, и массив содержит все элементы в этом списке (от первого до последнего элемента) // Возвращенная емкость массива определяется параметрами и большим значением в этом массиве @supresswarnings («un -проверка». Arrays.copyof (elementdata, size, a.getclass ()); System.ArrayCopy (elementData, 0, a, 0, size); if (a.length> size) a [size] = null; вернуть А; } // возвращать значение указанной позиции, поскольку это массив, он особенно быстр @suppresswarnings ("uncecked") e elementdata (int index) {return (e) elementdata [index]; } // возвращать значение указанной позиции, но проверьте, превышает ли количество позиций общедоступную длину массива e (int index) {rangecheck (index); return elementdata (index); } // Установите указанную позицию в новое значение и верните предыдущее значение, проверьте, превышает ли эта позиция общедоступное E Set (int index, e element) {rangecheck (index); E oldValue = elementData (индекс); elementData [index] = element; вернуть OldValue; } // Добавить значение первым обеспечивает емкость общедоступного логического добавления (e e) {eveRecapacityInternal (размер + 1); elementData [size ++] = E; вернуть истину; } // Добавить значение в указанную позицию и проверить добавленную позицию и емкость public void add (int index, e element) {rangecheckforadd (index); EnceRecapacityInternal (размер + 1); // public static void arraycopy (Object src, int srcpos, объект dest, int destpos, int length) // src: массив источников; SRCPOS: начальная позиция исходной массивы, которая будет скопирована; DEST: массив назначения; Destpos: начальная позиция массива назначения; Длина: Система длины копирования. Arraycopy (ElementData, Index, ElementData, Index + 1, Size - Index); elementData [index] = element; размер ++; } // Удалить значение указанной позиции, проверьте добавленную позицию и верните предыдущее значение public e Remove (int index) {rangecheck (index); modcount ++; E oldValue = elementData (индекс); 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); вернуть истину; }} вернуть false; } // быстро удалить значение в указанной позиции. Причина, по которой его называют быстро, должна заключаться в том, что нет необходимости проверять и возвращать значение, потому что только частная void 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, чтобы облегчить сбор мусора (в отличие от сброса, размер по умолчанию массива не будет сброшен, если он изменится) public void () {modcount ++; для (int i = 0; i <size; i ++) elementdata [i] = null; размер = 0; } // Добавить элемент коллекции к концу, если коллекция, которая должна быть добавлена, пуста, верните False Public Boolean Addall (Collection <? Extends E> C) {Object [] a = c.toarray (); int numnew = a.length; EncureCapacityInternal (размер + numnew); System.ArrayCopy (a, 0, elementData, size, numnew); размер += numnew; вернуть numnew! = 0; } // Функция такая же, как и выше, добавьте public boolean addall (int index, collection <? Extends e> c) {rangecheckforadd (index); Object [] a = c.toarray (); // массив, который должен быть добавлен int numnew = a.length; // длина добавленного массива ensureCapacityInternal (размер + numnew); // Убедитесь, что емкость int nummoved = size - index; // Длина, которая не будет двигаться (предыдущая часть), если (Nummoved> 0) // Если нет необходимости перемещать, копировать ее само по себе и перемещать заднюю часть массива в правильную систему положения. Arraycopy (elementData, index, elementData, index + numnew, nummaved); System.ArrayCopy (a, 0, elementData, index, numnew); // Добавить новый массив в середину измененного исходного размера массива += numnew; вернуть numnew! = 0; } // Удалить указанный элемент диапазона. Параметры представляют собой начальные и окончательные позиции, защищенные void remorsemange (int fromindex, int toindex) {modcount ++; int nummoved = size - toindex; // длина, сохраняемая в системе последнего сечения. Arraycopy (elementData, toIndex, elementData, fromIndex, Nummoved); int newsize = size - (toindex -fromindex); для (int i = newsize; i <size; i ++) {elementData [i] = null; } size = newsize; } // Проверьте, превышает ли число длины массива при добавлении элементов private void rangecheck (int index) {if (index> = size). Выбросить новый индекстуфундсексапс (outofboundsmsg (index)); } // Проверьте, является ли private void rangeCheckforadd (int index) {if (index> size || index <0) выбрать новый indexoutOfBoundSexception (OutOfBoundSmsg (index)); } // Подробная информация об исключении снятия частной строки OutOfBoundSmsg (int index)) {return "index:"+index+", size:"+size; } // Удалить элемент указанной коллекции public boolean removeall (collection <?> C) {objects.requirenonlonull (c); // Проверьте, является ли параметр null return batchremove (c, false); } // сохранить только элементы указанной коллекции public boolean retainall (collection <?> C) {objects.requirenonlonull (c); вернуть BatchRemove (c, true); }/** * Интерпретация исходного кода по http://anxpp.com/ * @param Заполните, когда истина, значение элемента в указанной коллекции сохраняется из массива, и когда false, значение элемента в указанной коллекции удаляется из массива. * @return Дубликаты элементов в массиве будут удалены (а не просто удаляются один раз или несколько раз), и любая операция удаления вернет True */ Private Boolean BatchRemove (Collection <?> C, Boolean Proctement) {Final Object [] elementData = this.elementData; int r = 0, w = 0; логический модифицированный = false; Попробуйте {// Transweep через массив и проверьте, содержит ли эта коллекция соответствующее значение, переместите значение, которое должно быть сохранено в переднюю часть массива, а последнее значение W - количество элементов, которые должны быть сохранены // Простая точка: если сохранить, переместите один и тот же элемент в предыдущий раздел; Если удалить, перемещайте разные элементы в предыдущий раздел для (; r <size; r ++) if (c.contains (elementdata [r]) == комплемент) elementdata [w ++] = elementdata [r]; } Наконец {// убедитесь, что часть перед выброшением исключения может завершить ожидаемую операцию, в то время как часть, которая не была пересечена, будет подключена к обратной // R! = Размер означает, что ошибка может произойти: C.Contains (elementData [r]) бросает исключение, если (r! w += size - r; } // Если W == Размер: означает, что все элементы сохраняются, поэтому операция удаления не происходит, поэтому FALSE будет возвращена; В противном случае, верно и массив // Когда w! = Размер возвращается, даже если блок Try вызывает исключение, операция до того, как исключение будет выброшено, потому что W всегда является длиной предыдущей части, которая должна быть сохранена, а массив не будет вне порядок, потому что (w! = size) {for (int i = w; i <size; i ++) elementdata [i] = null; modcount += size - w; // Количество изменений раз размер = w; // новый размер - это количество элементов, сохранившихся модифицированных = true; }} return modified; } // Сохранить состояние экземпляра массива в поток (то есть он сериализован). Массив процессов записи изменяется, и исключение будет брошено на частную void writeBject (java.io.objectOutputStream), бросает java.io.ioexception {int wedermodcount = modcount; S.DefaultWriteObject (); // Выполнить процесс десериализации/сериализации по умолчанию. Напишите нестатические и не трансляционные поля текущего класса в этот поток // Напишите в S.WriteInt (размер); // Напишите все элементы для (int i = 0; i <size; i ++) {s.writeObject (elementData [i]); } if (modcount! = wedermodcount) {бросить новый concurrentmodificationexception (); }} // написано выше, это читается. private void readobject (java.io.objectinputstream s) бросает java.io.ioexception, classnotfoundexception {elementData = empty_elementData; // Выполнить процесс сериализации/десериализации по умолчанию S.DefaulTReadObject (); // Читать в длине массива S.ReadInt (); if (size> 0) {EncureCapacityInternal (size); Object [] a = elementData; // Читать во всех элементах для (int i = 0; i <size; i ++) {a [i] = S.ReadObject (); }}}} // return listiceTerator, начальная позиция - это указанный параметр public listiceTerator <e> listiceTerator (int index) {if (index <0 || index> size) бросить новый indexoutofboundsexception ("index:"+index); вернуть новый список (индекс); } // return listiceTerator, начальная позиция - 0 Public ListIterator <e> ListIterator () {return New ListItr (0); } // вернуть обычный итератор public iterator <e> iterator () {return new itr (); } // Общий итератор реализует закрытый класс ITR реализует итератор <e> {int cursor; // курсор, индекс следующего элемента, инициализация по умолчанию составляет 0 int lastret = -1; // Положение последнего доступного элемента является int weardmodcount = modcount; // Процесс итерации не запускает модифицированный массив, в противном случае исключение будет брошено // Есть ли еще один общедоступный логический hasnext () {return cursor! = Size; } // Следующий элемент @suppresswarnings ("unchecked") public e next () {checkforComodification (); // Проверьте, изменяется ли массив int i = cursor; if (i> = size) бросить новый noshelementexception (); Object [] elementData = ArrayList.This.ElementData; if (i> = elementdata.length) бросить новый concurrentmodificationexception (); курсор = i + 1; // переместить курсор назад return (e) elementData [lastret = i]; // Установить позицию доступа и вернуть это значение} // Удалить элемент public void remoad () {if (lastret <0) бросить new allodalStateException (); checkforComodification (); // Проверьте, изменяется ли массив try {arraylist.this.remove (lastret); Cursor = lastret; lastret = -1; weddcount = modcount; } catch (indexoutOfBoundSexception ex) {бросить новый comproundModificationException (); }} @Override @suppresswarnings ("unchecked") public void foreCheraing (Consumer <? Super E> Consumer) {Objects.Requirenonllull (Consumer); окончательный int size = arraylist.tis.size; int i = курсор; if (i> = size) {return; } final Object [] elementData = arraylist.this.elementData; if (i> = elementdata.length) {бросить новый comproundModificationException (); } while (i! = size && modcount == weddcount) {consumer.accept ((e) elementData [i ++]); } cursor = i; lastret = i - 1; checkforComodification (); } // Проверьте, изменяется ли массив окончательный void checkforComodification () {if (modcount! = Wedermodcount). Выбросить новый comproundModificationException (); }} // ListIterator Iterator реализует Private Class Listitr Extens Itr Recaintions ListIterator <e> {listitr (int index) {super (); cursor = index; } public boolean hasprevious () {return cursor! = 0; } public int nextIndex () {return cursor; } public int int indIndex () {return cursor - 1; } @Suppresswarnings ("unchecked") public e предыдущий () {checkforComodification (); int i = курсор - 1; if (i <0) бросить новый noshelementexception (); Object [] elementData = ArrayList.This.ElementData; if (i> = elementdata.length) бросить новый concurrentmodificationexception (); курсор = i; вернуть (e) elementData [lastret = i]; } public void set (e e) {if (lastret <0) бросить new allodalstateexception (); checkforComodification (); try {arraylist.this.set (lastret, e); } catch (indexoutOfBoundSexception ex) {бросить новый comproundModificationException (); }} public void add (e e) {checkforComodification (); попробуйте {int i = cursor; Arraylist.his.add (i, e); курсор = i + 1; lastret = -1; weddcount = modcount; } catch (indexoutOfBoundSexception ex) {бросить новый comproundModificationException (); }}} // return subarray указанного общедоступного списка диапазона <e> sublist (int fromindex, int toindex) {sublistrangecheck (fromindex, toindex, size); вернуть новый сублист (это, 0, fromindex, toindex); } // Проверка безопасности static void sublistrangecheck (int fromindex, int toindex, int size) {if (fromIndex <0) бросить новый indexoutOfBoundSexception ("fromIndex =" + fromIndex); if (toIndex> size) бросить новый индексаутуфундсексапс ("toindex =" + toindex); if (fromIndex> toIndex) бросить new allogalArgumentException ("fromIndex (" + fromIndex + ")> toIndex (" + toindex + ")"); } // Subarray Private Class Sublist расширяет AbstractList <e> реализует randomAccess {private final AbstractList <e> parent; Частный финальный int parateroffset; Частный финал int смещении; int size; Sublist (AbstractList <e> родитель, 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.his.elementData (Offset + Index); Arraylist.his.elementdata [offset + index] = e; вернуть OldValue; } public e get (int index) {rangecheck (index); checkforComodification (); return arraylist.his.elementData (Offset + Index); } public int size () {checkforComodification (); вернуть это. size; } public void add (int index, e e) {rangecheckforadd (index); checkforComodification (); parent.add (parentoffset + index, e); this.modcount = parent.modcount; this.size ++; } public E удалить (int index) {rangecheck (index); checkforComodification (); E result = parent.remove (parentoffset + index); this.modcount = parent.modcount; это. size--; результат возврата; } Защищенный void remorsemange (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) вернуть false; checkforComodification (); parent.addall (parentoffset + index, c); this.modcount = parent.modcount; this.size += csize; вернуть истину; } public iterator <e> iterator () {return listiceTerator (); } public listiceTerator <e> listiceTerator (final int index) {checkforComodification (); rangecheckforadd (индекс); final int offset = this.offset; вернуть новый ListIterator <e> () {int cursor = index; int lastret = -1; int weddcount = arraylist.tis.modcount; public boolean hasnext () {вернуть курсор! = sublist.this.size; } @Suppresswarnings ("unchecked") public e next () {checkforComodification (); int i = курсор; if (i> = sublist.this.size) бросить новый noshelementexception (); Object [] elementData = ArrayList.This.ElementData; if (offset + i> = elementdata.length) бросить новый comproundModificationException (); курсор = i + 1; return (e) elementData [offset + (lastret = i)]; } public boolean hasprevious () {return cursor! = 0; } @Suppresswarnings ("unchecked") public e предыдущий () {checkforComodification (); int i = курсор - 1; if (i <0) бросить новый noshelementexception (); Object [] elementData = ArrayList.This.ElementData; if (offset + i> = elementdata.length) бросить новый comproundModificationException (); курсор = i; return (e) elementData [offset + (lastret = i)]; } @Suppresswarnings ("unchecked") public void foreachremaing (потребитель <? Super E> Consumer) {Objects.Requirenonlull (потребитель); окончательный int size = sublist.this.size; int i = курсор; if (i> = size) {return; } final Object [] elementData = arraylist.this.elementData; if (offset + i> = elementdata.length) {бросить новый comproundModificationException (); } while (i! = size && modcount == wedermodcount) {consumer.accep ((e) elementData [offset+(i ++)]); } // Обновление один раз в конце итерации, чтобы уменьшить кучу писать трафик lastret = coursor = i; checkforComodification (); } public int nextIndex () {return cursor; } public int int indIndex () {return cursor - 1; } public void remove () {if (lastret <0) бросить new allogalStateException (); checkforComodification (); try {sublist.this.remove (lastret); Cursor = lastret; lastret = -1; weddmodcount = arraylist.tis.modcount; } catch (indexoutOfBoundSexception ex) {бросить новый comproundModificationException (); }} public void set (e e) {if (lastret <0) бросить новый allodalstateexception (); checkforComodification (); try {arraylist.this.set (offset + lastret, e); } catch (indexoutOfBoundSexception ex) {бросить новый comproundModificationException (); }} public void add (e e) {checkforComodification (); попробуйте {int i = cursor; Sublist.his.add (i, e); курсор = i + 1; lastret = -1; weddmodcount = arraylist.tis.modcount; } catch (indexoutOfBoundSexception ex) {бросить новый comproundModificationException (); / }}; } public List <e> sublist (int fromindex, int toindex) {sublistrangecheck (fromindex, toindex, size); вернуть новый сублист (это, смещение, от Index, toindex); } private void rangecheck (int index) {if (index <0 || index> = this.size) бросить новый индекстуфунсексапс (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) бросить новый coundrentModificationException (); } public spliterator <e> splitterator () {checkforComodification (); вернуть новый ArraylistsPliterator <e> (ArrayList.This, смещение, смещение + this.size, this.modcount); }} @Override public void foreach (Consumer <? Super e> action) {objects.requirenonlull (action); final int weddcount = modcount; @Suppresswarnings ("unchecked") final e [] elementdata = (e []) this.elementdata; окончательный int size = this.size; for (int i = 0; modcount == weddcount && i <size; i ++) {action.accep (elementdata [i]); } if (modcount! = wedermodcount) {бросить новый concurrentmodificationexception (); }}/** * Создает <em> <a href = "spliterator.html#Binding" rel = "внешний nofollow"> позднее связывание </a> </em> * и <em> fail-fast </em> {@link spliterator} над элементами в этом списке *. * * <p> {@code spliterator} отчеты {@link spliterator#size}, * {@link spliterator#подчинен} и {@link spliterator#заказан}. * Переходящие реализации должны документировать отчет о дополнительных * характерных значениях. * * @return a {@code spliterator} над элементами в этом списке * @since 1.8 */ @override public spliterator <e> splitterator () {return new Arraylistspliterator <> (это, 0, -1, 0); } /** На основе индекса разделенные, ленивые инициализированные шлитроны * /Статический окончательный класс Аррейлист-плеститратор <e> реализует Spliterator <e> { / * * Если аратрелисты были неизменными, или структурно неизбежно (no * добавляет, удаляет и т. Д.), Мы могли бы реализовать их сплески * с Arrays.spliterator. Вместо этого мы обнаруживаем столько * вмешательства во время обхода, сколько практического, не жертвуя большим результатом. Мы полагаемся в первую очередь на * modcounts. Они не гарантируют обнаружение параллелизма * насилия, а иногда и чрезмерно консервативны в отношении * во время вмешательства, но обнаруживают достаточно проблем, чтобы * стоить на практике. Чтобы выполнить это, мы (1) лениво * Инициализируем забор и ожидаемый, до тех пор, пока не последняя * точка, которую нам нужно посвятить государству, с которым мы проверяем *; Таким образом, повышение точности. (Это не относится к * сублистам, которые создают сплиттеры с текущими не-ленивыми * значениями). (2) Мы выполняем только одну * concurrentmodificationException проверку в конце Foreach * (наиболее чувствительный к производительности метод). При использовании Foreach * (в отличие от итераторов) мы обычно можем обнаружить только * помехи после действий, а не раньше. Далее * CME-запускающие проверки применяются ко всем другим возможным * насилию допущений, например, NULL или Too Small * ElementData, учитывая его размер (), что могло произойти только из-за помех. Это позволяет внутренней петле * Foreach работать без каких-либо дополнительных проверок, и * упрощает разрешение Lambda. Хотя это влечет за собой * количество проверок, обратите внимание, что в общем случае * list.stream (). Foreach (a), никакие проверки или другие вычисления * не встречаются где -либо, кроме самого внутреннего форита. Другие * менее часто используемые методы не могут воспользоваться большинством этих оптимизаций. */ Private Final ArrayList <e> List; частный индекс Int; // текущий индекс, измененный на предварительном/разделении частного забора; // -1 до использования; затем один прошлый последний индекс private int weardcount; // инициализируется при наборе забора/ ** Создание нового шлиптора, охватывающего заданный диапазон*/ arraylistspliterator (ArrayList <e> List, int Origin, int forly, int wedmodcount) {this.list = list; // ОК, если null, если не пересекал это.index = Origin; this.fence = забор; this.expretmodcount = wedermodcount; } private int getFence () {// Инициализировать забор к размеру на первом использовании int hi; // (специализированный вариант появляется в методе Foreach) ArrayList <e> lst; if ((hi = farge) <0) {if ((lst = list) == null) hi = warn = 0; else {weardmodcount = lst.modcount; HI = FERNT = LST.SIZE; }} вернуть HI; } public arraylistspliterator <e> trysplit () {int hi = getfence (), lo = index, mid = (lo + hi) >>> 1; возврат (lo> = mid)? null: // divide arrange пополам, если только слишком маленький новый Arraylistspliterator <e> (List, lo, index = mid, weardmodcount); } 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(); вернуть истину; } вернуть 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++; }}Суммировать
The above is all about ArrayList source code analysis in Java programming, and I hope it will be helpful to everyone. Заинтересованные друзья могут продолжать ссылаться на другие связанные темы на этом сайте. Если есть какие -либо недостатки, пожалуйста, оставьте сообщение, чтобы указать это. Спасибо, друзья, за вашу поддержку на этом сайте!