Eu li uma frase antes, e foi muito bom. Alguém perguntou qual é a utilidade da leitura do código -fonte? Aprenda as idéias de design de outras pessoas para implementar uma determinada função e melhorar seu nível de programação.
Sim, todo mundo implementa uma função. Pessoas diferentes têm idéias de design diferentes. Algumas pessoas usam 10.000 linhas de código e outras usam 5.000 linhas. Algumas pessoas precisam executar o código por dezenas de segundos, enquanto outras precisam apenas de alguns segundos. . Vamos ao tópico abaixo.
Principal conteúdo deste artigo:
Comment Um comentário detalhado sobre a implementação do Arraylist, com base no JDK 1.8.
・A parte do sublista do iterador não foi explicada em detalhes e será colocada em outras interpretações do código -fonte. Aqui nos concentramos na implementação do próprio Arraylist.
・Nenhuma anotação padrão é usada e o indentação do código é ajustado adequadamente para facilitar a introdução
importar java.util.abstractList; importar java.util.arrays; importar java.util.bitset; importar java.util.Collection; importar java.util.comparator; importaterl.util.util.ConcurrentModificationException; import java.util.ItAtator; java.util.nosuchElementException; importar java.util.Objects; importar java.util.randomaccess; importar java.util.spliterator; importar java.util.function.Consumer; import java.util.function.furedsicate; interface que pode ser redimensionada. Implemente todas as operações da lista opcional e permita que todos os elementos, incluindo NULL, sejam repetíveis. * Além da interface da lista, esta classe fornece uma maneira de manipular o tamanho da matriz para armazenar o tamanho da matriz na lista. * * Complexidade do tempo: * As chamadas para o tamanho dos métodos, isEmpty, Get, Set, Iterator e Listiterator são tempo constante. * A complexidade do tempo de adição e exclusão é O (n). Todas as outras operações são complexidade do tempo linear. * * Capacidade: * Cada Arraylist tem capacidade e o tamanho da capacidade é pelo menos o comprimento do elemento da lista, e a inicialização padrão é 10. * A capacidade pode ser aumentada automaticamente. * Se você souber com antecedência que existem muitos elementos na matriz, poderá aumentar a capacidade com antecedência, chamando o método surCapacity () antes de adicionar elementos para reduzir a sobrecarga do crescimento da capacidade automática no período posterior. * Essa capacidade também pode ser inicializada por um construtor com capacidade inicial. * * Thread não é seguro: * ArrayList não é seguro. * Se precisar ser aplicado aos multithreads, a sincronização precisa ser feita externamente * * modCount: * definido no abstrataList: transitório protegido int modCount = 0; * Número de vezes esta lista foi modificada estruturalmente. A modificação estrutural refere -se à alteração do tamanho da lista ou à interrupção da lista, para que a iteração em andamento produz resultados incorretos. * Este campo é usado pelas implementações do iterador e listão o iterador retornado pelos métodos Iterator e Listerator. * Se o valor nesse campo for alterado acidentalmente, o iterador (ou o iterador de listagem) lançará uma concursão de concorrente em resposta a seguir, remover, anterior, definir ou adicionar operações. * Quando confrontado com modificações simultâneas durante as iterações, fornece comportamento com falha rápida, em vez de comportamento não determinístico. * Se a subclasse usa esse campo é opcional. * Se a subclasse desejar fornecer um iterador de falha rápido (e o iterador da lista), ele simplesmente adiciona esse campo aos métodos Add (int, e) e remove (int) (e quaisquer outros métodos que substitui, resultando em modificações na estrutura da lista). * O número de chamadas únicas para adicionar (int, e) ou remover (int) não deve exceder 1 a este campo, caso contrário, o iterador (e o iterador da lista) lançará o Fake ConcurrentModificationExceptions. * Se uma implementação não quiser fornecer um iterador de falha rápido, esse campo poderá ser ignorado. * * Transiente: * Por padrão, todas as variáveis de membro de um objeto serão persistidas. Em alguns casos, se você deseja evitar persistir algumas variáveis de membro de um objeto, pode usar a palavra -chave transitória para marcá -las, que também é uma palavra reservada em java (jdk 1.8) */public class ArrayList <E> estende abstratoList <e> implementa a lista <e>, aleatória, clonável, javsion.io.Serialll <e> List <e>, reclamado, clonável, javsion.io.Serialll Sternizll Sterilizll {Setrice Stermalizll {Randomid Stermatic {Setrista {Setrista {Setrista {Setrista {Setrista {Setrista {Setrissill Stermalizll Sterlizll… 8683452581122892189L; // Capacidade inicial padrão private estático final int default_capacity = 10; // usado para compartilhar instâncias de matriz vazia com instâncias vazias. Objeto final estático privado [] emailt_elementData = {}; // Matriz vazia padrão Objeto final estático privado [] defaultCapacity_empty_ElementData = {}; // Para a direita, a matriz de elementos, as permissões de acesso ao pacote são armazenadas objeto transitório [] elementData; // Tamanho, o Java inicializará o INT para 0 ao criar um tamanho privado Int Size; // Defina o construtor da capacidade de inicialização com o número especificado, e o número negativo lançará uma exceção public ArrayList (int InitialCapacity) {if (InitialCapacity> 0) {this.ElementData = novo objeto [InitialCapacity]; } else if (InitialCapacity == 0) {this.ElementData = vazio_ElementData; } else {lança nova ilegalArgumentException ("Capacidade ilegal:"+InitialCapacidade); }} // Construtor padrão, use a matriz de controle para inicializar public ArrayList () {this.ElementData = defaultCapacity_empty_ElementData; } // Construa uma lista que contém elementos na coleção na ordem do retorno do iterador da coleção Public ArrayList (coleção <? Extende e> c) {elementData = c.toarray (); if ((size = elementData.length)! = 0) {// c.toArray pode (erro) não retornar objeto [] (consulte Java Bug número 6260652) se (elementData.getclass ()! = objeto []. Class) elementData = Arrays.copyOf (ElementData, tamanho, objeto []. Class); } else {// use uma matriz vazia this.ElementData = emaillement_elementData; }} // porque a capacidade geralmente é maior que o número real de elementos. Quando a memória estiver apertada, você pode chamar esse método para excluir o local reservado e ajustar a capacidade do número real de elementos. // Se você tiver certeza de que nenhum elemento será adicionado, também pode chamar esse método para salvar o espaço public void TRIMTOSIZE () {modCount ++; if (size <elementData.length) {elementData = (size == 0)? Vazio_elementData: Arrays.copyof (elementData, tamanho); }} // Defina a capacidade da matriz com os parâmetros especificados public void EnsureCapacity (int mincapacity) {// Se a matriz estiver vazia, pré -busca 0, caso contrário, vá para o valor padrão (10) int minexpand = (ElementData! = DefaultCapacity_empty_ElementData)? 0: default_capacity; // Se o parâmetro for maior que a capacidade predefinida, use este parâmetro para definir ainda mais a capacidade da matriz se (MinCapacity> minexpand) {garantirexplicitCapacity (MinCapacity); }} // Ao adicionar elementos, verifique se a capacidade de matriz private vazio é a capacidade de capacidade (int mincapacity) {// use o valor padrão e o parâmetro maior como o valor predefinido da capacidade se (elementData == defaultCapacity_empty_ElementData) {minapacity = math.max (defaultCacity_apacity,, MinCacity; } garantirexplicitCapacity (Mincapacity); } // Se o parâmetro for maior que a capacidade da matriz, aumente a capacidade de matriz vazio privado garantirexplicCapacity (int mincapacity) {modCount ++; if (Mincapacity - ElementData.Length> 0) Grow (MinCapacity); } // A capacidade máxima da matriz pode causar excesso de memória (limite de memória vm) estático privado int max_array_size = Integer.max_value - 8; // Aumente a capacidade de garantir que ele possa conter pelo menos o número de elementos especificados pelo parâmetro Void Private Grow (int mincapacity) {int OldCapacity = ElementData.length; // Aumente a capacidade predefinida pela metade int newCapacity = OldCapacity + (OldCapacity >> 1); // pegue o valor maior do parâmetro if (newCapacity - MinCapacity <0) //, ou seja, NewCapacity <Mincapacity newCapacity = MINCAPACIDADE; // Se o valor predefinido for maior que o máximo padrão, verifique se ele transborda se (newCapacity - max_array_size> 0) newCapacity = hugecapacidade (mincapacidade); ElementData = Arrays.copyof (ElementData, NewCapacity); } // Verifique se ele transborda. Se não houver transbordamento, retorne o valor inteiro máximo (o int em Java é de 4 bytes, para que o máximo seja 0x7ffffffffff) ou o valor máximo padrão está estático privado int HugeCapacity (int mincapacity) {if (mincapacity <0) // Overflow lança novo outOfMemorRor (); Return (Mincapacity> max_array_size)? Integer.max_value: max_array_size; } // retorna o tamanho da matriz public int size () {return size; } // está vazio public boolean isEmpty () {return size == 0; } // Se ele contém um número, o retorno boole -boolean contém (objeto o) {return indexOf (o)> = 0; } // retorna um valor na primeira aparição da matriz e será julgado de maneiras diferentes com base em ser nulo. Se não existir, retorna -1. A complexidade do tempo é o (n) public int indexOf (objeto o) {if (o == null) {for (int i = 0; i <tamanho; i ++) if (elementData [i] == null) retornar i; } else {for (int i = 0; i <tamanho; i ++) se (o.equals (elementData [i])) retornar i; } retornar -1; } // retorna um valor na última vez em que aparece na matriz. Se não existir, retorna -1. A complexidade do tempo é o (n) public int lastIndexOf (objeto o) {if (o == null) {for (int i = size-1; i> = 0; i-) if (elementData [i] == null) retornar i; } else {for (int i = size-1; i> = 0; i-) se (o.equals (elementData [i])) retornar i; } retornar -1; } // Retorna a cópia, o elemento em si não foi copiado e uma exceção será lançada quando a matriz do processo de cópia mudar de objeto público clone () {try {ArrayList <?> V = (ArrayList <?>) Super.clone (); v.ElementData = Arrays.copyof (ElementData, tamanho); v.modCount = 0; retornar v; } catch (clonenotsupportEdException e) {tiro o novo internalError (e); }} // Converta em uma matriz de objetos, use o MATRAYS.COPYOF () Método Public Object [] ToArray () {return Arrays.copyof (elementData, size); } // Retorna uma matriz, use o tempo de execução para determinar o tipo e a matriz contém todos os elementos nesta lista (do primeiro ao último elemento) // A capacidade de matriz retornada é determinada pelos parâmetros e o valor maior nessa matriz @suppresswarnings ("desmarcada") public <T> t [] Toarray (t [] a) {senão (A. A. A. A. A. A. A. A. A. A. A. A. A. A. A. A. A. A. A. A. A. A. A. A. A. A. A. A.) Arrays.copyof (ElementData, Size, A.GetClass ()); System.arrayCopy (ElementData, 0, A, 0, tamanho); if (a.Length> tamanho) a [size] = null; retornar a; } // Retorna o valor da posição especificada, porque é uma matriz, é particularmente rápida @suppresswarnings ("desmarcado") e elementData (int index) {return (e) elementData [index]; } // Retorna o valor da posição especificada, mas verifique se o número de posições excede o comprimento da matriz public e get (int index) {rangecheck (index); retornar elementData (índice); } // Defina a posição especificada como um novo valor e retorne o valor anterior, verifique se essa posição excede o comprimento da matriz Public E Set (índice int, e elemento) {Rangecheck (index); E OldValue = ElementData (índice); elementData [index] = elemento; retornar OldValue; } // Adicione um valor garante primeiro a capacidade de add boolean público (e e) {securecapacityInternal (tamanho + 1); ElementData [size ++] = e; retornar true; } // Adicione um valor na posição especificada e verifique a posição e a capacidade adicionadas public void add (int index, e elemento) {ranngecheckforadd (index); garantir o internal (tamanho + 1); // public static void Arraycopy (objeto src, int srcpos, objeto dest, int destpos, int length) // src: matriz de origem; SRCPOS: a posição inicial da matriz de origem a ser copiada; Dest: Array de destino; destpos: a posição inicial da matriz de destino; Comprimento: cópia de comprimento System.arraycopy (elementData, índice, elementoData, índice + 1, tamanho - índice); elementData [index] = elemento; tamanho ++; } // Exclua o valor da posição especificada, verifique a posição adicionada e retorne o valor anterior public e remover (int index) {Rangecheck (index); modCount ++; E OldValue = ElementData (índice); int numMoved = size - índice - 1; if (numMoved> 0) System.arrayCopy (ElementData, Index+1, ElementData, Index, numMoved); elementData [-size] = null; // Fácil de reciclar o período de coleta de lixo retorna antigo; } // Exclua o local em que o elemento especificado aparece primeiro public boolean Remover (objeto o) {if (o == null) {for (int index = 0; index <size; index ++) if (elementData [index] == null) {fastremove (index); retornar true; }} else {for (int index = 0; index <size; index ++) if (o.equals (elementData [index])) {fastremove (index); retornar true; }} retornar false; } // Exclua rapidamente o valor na posição especificada. A razão pela qual é chamado FAST deve ser que não há necessidade de verificar e retornar o valor, porque apenas o Fastremove privado do vazio privado (int index) {modCount ++; int numMoved = size - índice - 1; if (numMoved> 0) System.arrayCopy (ElementData, Index+1, ElementData, Index, numMoved); elementData [-size] = null; // Limpe para permitir que o GC faça seu trabalho} // limpe a matriz e defina cada valor para anular para facilitar a coleta de lixo (diferentemente da redefinição, o tamanho padrão da matriz não será redefinido se mudar) public void clear () {modCount ++; for (int i = 0; i <tamanho; i ++) elementData [i] = null; tamanho = 0; } // Adicione um elemento de uma coleção ao final, se a coleção a ser adicionada estiver vazia, retorne False Public Boolean Addall (coleção <? Extende e> c) {objeto [] a = c.toarray (); int numNew = A.Length; garantir o internal (tamanho + numNew); System.arraycopy (a, 0, elementData, tamanho, numNew); tamanho += numNew; retornar numNew! = 0; } // A função é a mesma que acima, adicione public boolean addall (índice int, coleta <? Estende e> c) {rangecheckforadd (index); Objeto [] a = c.toArray (); // a matriz a ser adicionada int numNew = A.Length; // o comprimento da matriz a ser adicionado, EnsureCapacityInternal (tamanho + numNew); // verifique se a capacidade int nummoved = tamanho - índice; // o comprimento que não se moverá (a parte anterior) se (nummoved> 0) // se não houver necessidade de se mover, copie -o por si só e mova a parte traseira da matriz para o sistema de posição correto.arraycopy (elementData, índice, elementData, índice + numNew, numMoved); System.ArrayCopy (A, 0, ElementData, Index, NumNew); // Adicione nova matriz ao meio do tamanho da matriz original alterado += numNew; retornar numNew! = 0; } // Exclua o elemento de intervalo especificado. Os parâmetros são as posições iniciais e finais de remoção vazia protegida (int a partir derincex, int toIndex) {modCount ++; int numMoved = size - toIndex; // o comprimento retido pelo último sistema de seção.arraycopy (ElementData, ToIndex, ElementData, Fromindex, numMoved); int newsize = size - (toIndex -fromindex); for (int i = notwsize; i <tamanho; i ++) {elementData [i] = null; } size = newsize; } // Verifique se o número excede o comprimento da matriz ao adicionar elementos privados void rangecheck (int index) {if (index> = size) lança novo indexOutOfBoundSexception (outOfboundsmsg (index)); } // Verifique se o vazio privado RangecheckForAdd (int index) {if (índice> size || índice <0) lança o novo indexOutOfBoundSexception (outOfBoundSmsg (index)); } // Detalhes da exceção arremessada String privada outOfBoundSmsg (int index)) {return "index:"+index+", size:"+size; } // Exclua o elemento da coleção especificada Public boolean removeall (coleção <?> C) {objects.requiteNonNull (c); // verifique se o parâmetro é NULL Return BatchRemove (c, false); } // reter apenas os elementos da coleção especificada Public boolean reternalall (coleção <?> C) {objects.RequirenOnnull (c); retornar BatchRemove (C, True); }/** * Interpretação do código -fonte por http://anxpp.com/ * @param completo quando true, o valor do elemento na coleção especificado é retido da matriz e, quando false, o valor do elemento na coleção especificado é excluído da matriz. * @Return Os elementos duplicados na matriz serão excluídos (em vez de apenas excluídos uma ou várias vezes), e qualquer operação de exclusão retornará verdadeira */ private booleano BatchRemove (coleção <?> c, complemento booleano) {final objeto [] elementData = this.ElementData; int r = 0, w = 0; booleano modificado = false; tente {// transweep através da matriz e verifique se esta coleção contém o valor correspondente, mova o valor a ser retido para a frente da matriz e o último valor de w é o número de elementos a serem mantidos // ponto simples: se retido, mova o mesmo elemento para a seção anterior; Se excluído, mova elementos diferentes para a seção anterior para (; r <tamanho; r ++) se (c.contains (elementData [r]) == complement) elementData [w ++] = elementData [r]; } finalmente {// verifique se a parte antes que a exceção seja lançada possa concluir a operação esperada, enquanto a parte que não foi percorrida será conectada ao traseiro // r! = tamanho significa que pode ocorrer um erro: c.contains (elementData [r]) lança uma exceção se (r! = size) {size. w += tamanho - r; } // Se w == Tamanho: significa que todos os elementos são retidos, portanto, nenhuma operação de exclusão ocorre, portanto, false será retornado; Caso contrário, verdadeiro e a matriz // quando W! = O tamanho é retornado, mesmo que o Block de Try jogue uma exceção, a operação antes que a exceção seja lançada, porque W é sempre a duração da parte anterior a ser retida e a matriz não ficará fora de ordem porque (w! modCount += tamanho - w; // o número de vezes alterado tamanho = w; // O novo tamanho é o número de elementos preservados modificados = true; }} retornar modificado; } // Salvar o estado da instância da matriz em um fluxo (ou seja, é serializado). A matriz de processos de gravação é alterada e uma exceção será lançada private void writeObject (java.io.ObjectOutputStream s) lança java.io.ioException {int esperamodCount = modCount; s.defaultWriteObject (); // Execute o processo de deserialização/serialização padrão. Escreva campos não estáticos e não transitórios da classe atual para este fluxo // Escreva para tamanho S.WriteInt (tamanho); // Escreva todos os elementos para (int i = 0; i <tamanho; i ++) {s.WriteObject (elementData [i]); } if (modCount! = esperadoModCount) {lança new concurrentModificationException (); }} // O acima está escrito, isso é lido. private void readObject (java.io.ObjectInputStream s) lança java.io.ioException, classNotfoundException {elementData = emaillement_elementData; // executa o processo de serialização/deserialização padrão s.defaultreadObject (); // leia no comprimento da matriz s.readInt (); if (size> 0) {securecApacityInternal (tamanho); Objeto [] a = elementData; // leia em todos os elementos para (int i = 0; i <tamanho; i ++) {a [i] = s.readObject (); }}}} // Return listiterator, a posição inicial é o parâmetro especificado listiterator <e> listiterator (int index) {if (index <0 || índice> size) lança novo indexOutOfBoundSexception ("índice:"+índice); retornar novo listitr (índice); } // Return listiterator, a posição inicial é 0 listiterator public <e> listiterator () {return new listitr (0); } // return iterator comum iterator <e> iterator () {return new itr (); } // O iterador geral implementa a classe privada ITR implementa o iterador <E> {int cursor; // O cursor, o índice do próximo elemento, a inicialização padrão é 0 int lastret = -1; // A posição do último elemento acessada é esperada ModCount = modCount; // O processo de iteração não executa a matriz modificada, caso contrário, uma exceção será lançada // existe outro booleano público hasnext () {return cursor! = Size; } // O próximo elemento @suppresswarnings ("desmarcado") public e next () {checkForComodification (); // Verifique se a matriz é modificada int i = cursor; if (i> = size) lança novos nosuchElementException (); Objeto [] ElementData = ArrayList.This.ElementData; if (i> = elementData.length) lança nova concurrentmodificationException (); cursor = i + 1; // mova o cursor para trás retorno (e) elementData [lastret = i]; // Defina a posição de acesso e retorne este valor} // Exclua o elemento public void remover () {if (lastret <0) lança new ilegalStateException (); checkForComodification (); // Verifique se a matriz é modificada, tente {ArrayList.this.remove (lastret); cursor = lastret; lastret = -1; esperadomodCount = modCount; } catch (indexOutOfBoundSexception ex) {tiro novo concurrentModificationException (); }} @Override @suppresswarnings ("desmarcado") public void foreachRemaining (consumidor <? Super e> consumer) {objects.requiirOnonLull (consumidor); final int size = ArrayList.This.size; int i = cursor; if (i> = size) {return; } objeto final [] elementData = ArrayList.This.ElementData; if (i> = elementData.length) {lança novo concurrentModificationException (); } while (i! = size && modCount == esperamModCount) {consumer.accept ((e) elementData [i ++]); } cursor = i; lastret = i - 1; checkForComodification (); } // Verifique se a matriz é modificada Final Void CheckForComodification () {if (modCount! = EsperamodCount) lança nova concurrentmodificationException (); }} // O ITERATOR LISTITERATOR implementa a classe privada Listitr estende o ITR implementa o listiterator <E> {listitr (int index) {super (); cursor = index; } public boolean hasprevious () {return cursor! = 0; } public int nextIndex () {return cursor; } public int anteriorIndex () {return cursor - 1; } @Suppresswarnings ("desmarcado") public e anterior () {checkForComodification (); int i = cursor - 1; if (i <0) lançar novos nosuchElementException (); Objeto [] ElementData = ArrayList.This.ElementData; if (i> = elementData.length) lança nova concurrentmodificationException (); cursor = i; return (e) elementData [lastret = i]; } public void set (e e) {if (lastret <0) lança new ilegalStateException (); checkForComodification (); tente {ArrayList.This.Set (lastret, e); } catch (indexOutOfBoundSexception ex) {tiro novo concurrentModificationException (); }} public void add (e e) {checkForComodification (); tente {int i = cursor; ArrayList.This.add (i, e); cursor = i + 1; lastret = -1; esperadomodCount = modCount; } catch (indexOutOfBoundSexception ex) {tiro novo concurrentModificationException (); }}} // Retorne subarray da lista pública de intervalo especificada <E> sublist (int deindex, int toIndex) {subblinstangecheck (deindex, toIndex, tamanho); retornar novo sublist (isto, 0, deindex, toIndex); } // Segurança Verifique o void estático SUBLIRANGECHECK (int a partir de Index, int toIndex, int size) {if (fromIndex <0) lança novo indexOutOfBoundSexception ("deindex =" + fromIndex); if (toIndex> size) lança novo indexOutOfBoundSexception ("toIndex =" + toIndex); if (FromIndex> toIndex) lançar novas ilegalargumentException ("FromIndex (" + FromIndex + ")> toIndex (" + toIndex + ")"); } // Subarraia a classe privada sublist estende o abstratoList <E> implementa RandomAccess {Private Final AbstractList <E> Parent; Final privado Int ParentOffset; Offset final privado int; Int tamanho; Sublist (abstractlist <e> pai, int offset, int a partir deindex, int toIndex) {this.parent = pai; 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 (deslocamento + índice); ArrayList.This.ElementData [deslocamento + índice] = e; retornar OldValue; } public e get (int index) {rangecheck (index); checkForComodification (); return ArrayList.This.ElementData (deslocamento + índice); } public int size () {checkForComodification (); devolver este.size; } public void add (int index, e e) {rangecheckforadd (index); checkForComodification (); parent.add (ParentOffSet + Index, e); this.modCount = parent.modcount; this.size ++; } public e remover (int index) {Rangecheck (index); checkForComodification (); E resultado = parent.Remove (ParentOffSet + Index); this.modCount = parent.modcount; this.size--; resultado de retorno; } Removerange vazio protegido (int deindex, int toIndex) {checkForComodification (); Parent.RemOverRange (ParentOffset + FromIndex, Parentoffset + ToIndex); this.modCount = parent.modcount; this.size - = ToIndex - FromIndex; } public boolean addall (coleção <? estende e> c) {return addall (this.size, c); } public boolean addall (índice int, coleta <? estende e> c) {rangecheckforadd (index); int csize = c.size (); if (csize == 0) retorna false; checkForComodification (); parent.addall (ParentOffset + Índice, c); this.modCount = parent.modcount; this.size += csize; retornar true; } public iterator <e> iterator () {return listiterator (); } public listiterator <e> listiterator (Índice final int) {checkForComodification (); Rangecheckforadd (índice); final int offset = this.offset; Retorne o novo listiterator <E> () {int cursor = index; int lastret = -1; int esperamodCount = ArrayList.This.modCount; public boolean hasNext () {return cursor! = sublist.this.size; } @Suppresswarnings ("desmarcado") public e next () {checkForComodification (); int i = cursor; if (i> = sublist.This.size) lançar novas NosuchElementException (); Objeto [] ElementData = ArrayList.This.ElementData; if (offset + i> = elementData.length) lança nova concurrentmodificationException (); cursor = i + 1; return (e) elementData [deslocamento + (lastret = i)]; } public boolean hasprevious () {return cursor! = 0; } @Suppresswarnings ("desmarcado") public e anterior () {checkForComodification (); int i = cursor - 1; if (i <0) lançar novos nosuchElementException (); Objeto [] ElementData = ArrayList.This.ElementData; if (offset + i> = elementData.length) lança nova concurrentmodificationException (); cursor = i; return (e) elementData [deslocamento + (lastret = i)]; } @Suppresswarnings ("desmarcado") public void foreachRemaining (consumidor <? Super e> consumer) {objects.requiirononnull (consumidor); final int size = sublist.This.size; int i = cursor; if (i> = size) {return; } objeto final [] elementData = ArrayList.This.ElementData; if (offset + i> = elementData.length) {lança novo concurrentModificationException (); } while (i! = size && modCount == esperamModCount) {consumer.accept ((e) elementData [deslocamento+(i ++)]); } // Atualizar uma vez no final da iteração para reduzir o tráfego de gravação de heap lastret = cursor = i; checkForComodification (); } public int nextIndex () {return cursor; } public int anteriorIndex () {return cursor - 1; } public void remover () {if (lastret <0) lança new ilegalStateException (); checkForComodification (); tente {sublist.this.remove (lastret); cursor = lastret; lastret = -1; esperadomodCount = ArrayList.This.ModCount; } catch (indexOutOfBoundSexception ex) {tiro novo concurrentModificationException (); }} public void set (e e) {if (lastret <0) lança new ilegalStateException (); checkForComodification (); tente {ArrayList.This.Set (deslocamento + lastret, e); } catch (indexOutOfBoundSexception ex) {tiro novo concurrentModificationException (); }} public void add (e e) {checkForComodification (); tente {int i = cursor; Sublist.This.add (i, e); cursor = i + 1; lastret = -1; esperadomodCount = ArrayList.This.ModCount; } catch (indexOutOfBoundSexception ex) {tiro novo concurrentModificationException (); }} Final void checkForComodification () {if (esperadoModCount! = ArrayList.This.ModCount) LIGUE NOVA CONCURNONTMODIFICIFCECCECTION (); }}; } Lista pública <E> sublist (int deindex, int toIndex) {subblinstangecheck (fromIndex, toIndex, size); devolver novos sublists (isto, deslocamento, FromIndex, ToIndex); } private void rangecheck (int index) {if (índice <0 || index> = this.size) lança novo indexOutOfBoundSexception (outOfBoundsmsg (index)); } private void Rangecheckforadd (int index) {if (index <0 || index> this.size) lança novo indexOutOfBoundSexception (outOfBoundsmsg (index)); } String privada outOfBoundsmsg (int index) {return "index:"+index+", size:"+this.size; } private void checkForComOdification () {if (ArrayList.this.modCount! = this.modCount) lança novo concurrentmodificationException (); } public spliterator <e> splitterator () {checkForComodification (); Retorne novos ArrayListsPliterator <E> (ArrayList.This, Offset, Offset + this.size, this.modCount); }} @Override public void foreach (consumidor <? Super e> ação) {objects.requiirenonnull (ação); final int esperamodCount = modCount; @Suppresswarnings ("desmarcado") e [] elementData = (e []) this.ElementData; final int size = this.size; for (int i = 0; modCount == esperamModCount && i <size; i ++) {action.accept (elementData [i]); } if (modCount! = esperadoModCount) {lança new concurrentModificationException (); }}/** * Cria um <em> <a href = "spliterator.html#encadernação" rel = "nofollow externo"> tardio </a> </em> * e <em> fail-fast </em> {@link spliterator} sobre os elementos desta lista *. * * <p> O {@code spliterator} relatórios {@link spliterator#tamanho}, * {@link spliterator#subssed} e {@link splitorator#ordenado}. * As implementações domésticas devem documentar o relatório de valores característicos adicionais *. * * @return a {@code spliterator} sobre os elementos nesta lista * @since 1.8 */ @Override public spliterator <e> splitterator () {retorna new ArrayListsPliterator <> (this, 0, -1, 0); } /** Spliterator baseado em índice baseado em índice, spliterator preguiçoso * /estático de classe final ArrayListsPliterator <E> implementa Spliterator <E> { / * * se os Arraylists fossem imutáveis ou estruturalmente imutáveis (não adds, Removes, etc.), poderíamos implementar seus flasters * com prisivos.splter. Em vez disso, detectamos tanta interferência durante a travessia como prática sem * sacrificar muito desempenho. Contamos principalmente em * modcounts. Isso não é garantido para detectar a violência de simultaneidade * e às vezes é excessivamente conservador sobre a interferência dentro do thread, mas detecta problemas suficientes para * valer a pena na prática. Para realizar isso, nós (1) preguiçosamente * inicializamos a cerca e esperou o ModCount até o mais recente ponto * que precisamos nos comprometer com o estado contra o qual estamos verificando *; melhorando assim a precisão. (Isso não se aplica a * sublists, que criam divisores com valores atuais não preguiçosos). (2) Realizamos apenas uma única verificação de * ConcurrentModificationException no final do foreach * (o método mais sensível ao desempenho). Ao usar o foreach * (em oposição aos iteradores), normalmente podemos detectar apenas * interferência após ações, não antes. Além disso, as verificações de província de CME se aplicam a todas as outras possíveis * violência de suposições, por exemplo, matriz nula ou muito pequena * elementData, dado seu tamanho (), que só poderia ter ocorrido devido a interferência. Isso permite que o loop interno * da FOREACH funcione sem mais verificações e * simplifica a resolução lambda. Embora isso implique um número * de cheques, observe que, no caso comum de * list.stream (). Foreach (a), sem verificações ou outra computação * ocorre em qualquer lugar que não seja o interior. Os outros métodos * menos usados não podem tirar proveito da maioria desses racionalizações. */ Lista de Arraylist final privada <E>; índice privado int; // Índice atual, modificado na cercagem privada de avanço/divisão; // -1 até ser usado; Então, um último índice privado privado e esperado modcount; // Inicializado quando o conjunto de cerca/ ** Crie um novo Spliterator cobrindo o intervalo especificado*/ ArrayListsPliterator (Lista ArrayList <E>, Int Origin, Int Fence, Int WeemerModCount) {this.list = list; // ok se nulo, a menos que atravessasse this.index = origem; this.fence = cerca; this.EliquedModCount = esperadoModCount; } private int getfence () {// Inicialize a cerca para dimensionar primeiro use Int Hi; // (uma variante especializada aparece no método foreach) Arraylist <e> lst; if ((hi = cerca) <0) {if ((lst = list) == null) oi = cerca = 0; else {esperamModCount = lst.modCount; oi = cerca = lst.size; }} retornar oi; } public ArrayListsPliterator <E> trysplit () {int hi = getfence (), lo = índice, mid = (lo + hi) >>> 1; retornar (lo> = médio)? NULL: // Divida o alcance ao meio, a menos que seja muito pequeno novo ArrayListsPliterator <E> (List, lo, index = MID, esperadoModCount); } 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; } retornar 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++; }}Resumir
The above is all about ArrayList source code analysis in Java programming, and I hope it will be helpful to everyone. Amigos interessados podem continuar se referindo a outros tópicos relacionados neste site. Se houver alguma falha, deixe uma mensagem para apontá -la. Obrigado amigos pelo seu apoio para este site!