Frequentemente usamos a interface iterativa fornecida pelo JDK para iterar as coleções Java.
Iterator iterator = list.iterator (); while (iterator.hasnext ()) {string string = iterator.next (); // faça algo} A iteração pode realmente ser simplesmente entendida como atravessada. É uma classe de método que padroniza a travessia de todos os objetos em vários contêineres. É um padrão de design muito típico. O padrão do iterador é um método de acesso padrão usado para atravessar aulas de coleta. Abstrai a lógica de acesso de diferentes tipos de classes de coleta, evitando expor a estrutura interna da coleção ao cliente. É assim que lidamos com isso quando não há iterador. do seguinte modo:
Para matrizes, usamos subscritos para processar:
int [] Arrays = new int [10]; para (int i = 0; i <arrays.length; i ++) {int a = matrizes [i]; // faça algo} É assim que o ArrayList é tratado:
List <String> list = new ArrayList <String> (); for (int i = 0; i <list.size (); i ++) {string string = list.get (i); // faça algo} Para ambos os métodos, sempre sabemos com antecedência a estrutura interna da coleção. O código de acesso e a coleção são fortemente acoplados e não podem separar a lógica de acesso da classe de coleta e código do cliente. Ao mesmo tempo, cada coleção corresponde a um método de travessia e o código do cliente não pode ser reutilizado. Em aplicações práticas, é bastante problemático integrar os dois conjuntos acima. Portanto, para resolver os problemas acima, o modo iterador está vago e sempre usa a mesma lógica para atravessar a coleção. Isso torna o próprio cliente desnecessário para manter a estrutura interna da coleção e todos os estados internos são mantidos pelo iterador. O cliente nunca lida diretamente com a classe de coleta. Ele sempre controla o iterador e o envia "para a frente", "para trás" e "pegue os comandos do elemento atual", e pode indiretamente atravessar toda a coleção.
O exposto acima é apenas uma breve explicação do padrão do iterador. Vamos dar uma olhada na interface do iterador em Java para ver como isso a implementa.
1. Java.util.iterator
Em Java, o iterador é uma interface, que fornece apenas regras básicas iterativas. No JDK, é definido assim: um iterador que itera na coleção. O iterador substitui a enumeração na estrutura de coleções Java. Existem duas diferenças entre iteradores e enumerações:
1. O iterador permite que o chamador remova os elementos da coleção apontada pelo iterador durante a iteração usando semântica bem definida.
2. O nome do método foi melhorado.
A definição de interface é a seguinte:
interface pública iterator {boolean hasNext (); Objeto a seguir (); void remove ();} em:
Objeto a seguir (): Retorna a referência ao elemento que o iterador apenas atravessa. O valor de retorno é objeto, que precisa ser lançado para o tipo que você precisa.
boolean hasNext (): determina se existem elementos disponíveis no contêiner para acessar
void remover (): remova o elemento que o iterador acabou de cruzar
Para nós, precisamos apenas usar a seguir () e HasNext () para concluir a iteração. do seguinte modo:
for (iterator it = c.iterator (); it.hasnext ();) {objeto o = it.next (); // Faça algo} A explicação anterior é que o iterador tem uma grande vantagem, ou seja, não precisamos conhecer os resultados internos do conjunto. A estrutura interna e o estado do conjunto são mantidos pelo iterador. Julgamos e obtemos o próximo elemento através dos métodos unificados HasNext () e Next (). Quanto à implementação interna específica, não precisamos nos preocupar com isso. Mas como programador qualificado, é muito necessário descobrir a implementação do iterador. O código -fonte do ArrayList é analisado abaixo.
2. Implementação do iterador para cada coleção
Vamos analisar a implementação do iterador do ArrayList. De fato, se entendermos as estruturas de dados da ArrayList, Hashset e Treeset e implementarem internamente, estaremos confiantes sobre como eles implementam o Iterator. Como a implementação interna do Arraylist usa uma matriz, precisamos apenas registrar o índice da posição correspondente e a implementação de seu método é relativamente simples.
2.1. Implementação do iterador do Arraylist
Inside ArrayList, primeiro define uma ITR de classe interna, que implementa a interface do iterador, como segue:
classe privada ITR implementa o iterador <E> {// Faça algo} E o método iterator () do ArrayList é implementado:
public iterator <e> iterator () {return new itr ();} Portanto, o método de ArrayList.iterator () retorna a classe interna iTR (), então o que precisamos nos preocupar agora é a implementação da classe interna iTR ():
Três variáveis do tipo int são definidas dentro do ITR: Cursor, Lastret e esperado ModCount. onde o cursor representa a posição do índice do próximo elemento, e Lastret representa a posição do índice do elemento anterior
int cursor; int lastret = -1; int esperamodCount = modCount;
A partir das definições de cursor e lastret, pode -se observar que o Lastret sempre foi um menos que o cursor; portanto, o método de implementação do hasNext () é extremamente simples. Você só precisa julgar se o cursor e o lastret são iguais.
public boolean hasNext () {return cursor! = size;} A implementação de Next () é realmente relativamente simples. Basta devolver o elemento na posição do índice do cursor e modificar o cursor e o lastret
public e next () {checkForComodification (); int i = cursor; // Posição do índice registrado if (i> = size) // Se o elemento obtê -lo for maior que o número de elementos de coleta, uma exceção será lançada no novo noscheLementException (); objeto [] elementData = ArrayList.This.ElementData; if (i> = elementData.length) lançar novo concurrentmodificationException (); cursor = i + 1; // cursor + 1return (e) elementData [lastret = i]; // lastret + 1 e retorne o elemento em cursor} O checkForComodification () é usado principalmente para determinar se o número de modificações de um conjunto é legal, ou seja, para determinar se o conjunto foi modificado durante o processo de travessia. O ModCount é usado para registrar o número de modificações da coleção ArrayList, inicializado em 0 e sempre que a coleção for modificada uma vez (a atualização interna não conta para a estrutura), como Adicionar, Remover e outros métodos, ModCount + 1, portanto, se o modcownt permanecer inalterado, significa que o conteúdo da coleção não foi modificado. Esse mecanismo é usado principalmente para implementar o mecanismo de falha rápida da coleção Arraylist. Nas coleções de Java, grande parte das coleções tem um mecanismo de falha rápida. Não vou falar sobre isso aqui e falarei sobre isso mais tarde. Portanto, para garantir que não haja erros durante o processo de travessia, devemos garantir que não haja modificações estruturais na coleção durante o processo de travessia (exceto o método de remoção). Se ocorrer um erro de exceção, devemos verificar cuidadosamente se o programa tem um erro em vez de não processá -lo após a captura.
Final Void CheckForComodification () {if (modCount! = esperammodCount) LIGUE NOVA CONCURNONTMODIFICIFCICECTIFECCETION ();} O método REMOT () é uma implementação, que chama o método REMOVE () de ArrayList para excluir o elemento Lastret Position e, em seguida, modificar o ModCount.
public void remover () {if (lastret <0) lançar new ilegalStateException (); checkForComodification (); tente {ArrayList.This.Remove (lastret); cursor = lastret; lastretTret = -1; esperamodCount = ModCount;} Catch (indexOutOptException).O exposto acima é o método de implementação da iteração do iterador de coleta Java introduzida a você pelo editor. Espero que seja útil para você. Se você tiver alguma dúvida, deixe -me uma mensagem e o editor responderá a você a tempo. Muito obrigado pelo seu apoio ao site wulin.com!