Domanda

Ho appena appreso come Java Collections Framework implementa le strutture dati negli elenchi collegati.Da quello che ho capito, Iterators sono un modo per attraversare gli elementi in una struttura dati come un elenco.Perché viene utilizzata questa interfaccia?Perché i metodi hasNext(), next() E remove() non direttamente codificato per l'implementazione della struttura dati stessa?

Dal sito Web Java: testo del collegamento

Iteratore dell'interfaccia pubblica<E>

Un iteratore su una collezione.Iteratore prende il posto dell'enumerazione nel framework delle collezioni Java.Gli iteratori differiscono dalle enumerazioni in due modi:

  • Gli iteratori consentono al chiamante di rimuovere gli elementi dalla raccolta sottostante durante l'iterazione con semantica ben definita.
  • I nomi dei metodi sono stati migliorati.
Questa interfaccia è membro del framework di collezioni Java.

Ho provato a cercare su Google e non riesco a trovare una risposta definitiva.Qualcuno può far luce sul motivo per cui Sun ha scelto di usarli?È a causa di un design migliore?Maggiore sicurezza?Buona pratica OO?

Qualsiasi aiuto sarà molto apprezzato.Grazie.

È stato utile?

Soluzione

Perché viene utilizzata questa interfaccia?

Perché supporta le operazioni di base che consentirebbero a un programmatore client di eseguire iterazioni su qualsiasi tipo di raccolta (nota:non necessariamente a Collection nel Object senso).

Perché i metodi...Non direttamente codificato sull'implementazione della struttura dei dati stessa?

Lo sono, sono semplicemente contrassegnati come Privati, quindi non puoi toccarli e giocarci.Più specificamente:

  • Puoi implementare o creare una sottoclasse an Iterator in modo tale che faccia qualcosa che quelli standard non fanno, senza dover alterare l'oggetto reale su cui esegue l'iterazione.
  • Gli oggetti che possono essere attraversati non hanno bisogno di avere le loro interfacce ingombre di metodi di attraversamento, in particolare di metodi altamente specializzati.
  • Puoi distribuire Iterators a tutti i clienti che desideri e ogni cliente può viaggiare nel proprio tempo, alla propria velocità.
  • Giava Iterators dal pacchetto java.util in particolare genererà un'eccezione se l'archiviazione che li supporta viene modificata mentre hai ancora un file Iterator fuori.Questa eccezione ti consente di sapere che il file Iterator ora potrebbe restituire oggetti non validi.

Per i programmi semplici, probabilmente nulla di tutto ciò sembra utile.Tuttavia, il tipo di complessità che li rende utili ti verrà in mente rapidamente.

Altri suggerimenti

Tu chiedi:"Perché i metodi hasNext(), next() e delete() non sono codificati direttamente nell'implementazione della struttura dati stessa?".

Il framework Java Collections sceglie di definire l'interfaccia Iterator come esternalizzata alla raccolta stessa.Normalmente, poiché ogni raccolta Java implementa il file Iterable interfaccia, verrà chiamato un programma Java iterator per creare il proprio iteratore in modo che possa essere utilizzato in un ciclo.Come altri hanno sottolineato, Java 5 ci consente di utilizzare direttamente l'iteratore, con un ciclo for-each.

L'esternalizzazione dell'iteratore alla sua raccolta consente al client di controllare il modo in cui si esegue l'iterazione attraverso una raccolta.Un caso d'uso a cui riesco a pensare in cui ciò è utile è quando si ha una raccolta illimitata come tutte le pagine Web su Internet da indicizzare.

Nel classico libro GoF, il contrasto tra iteratori interni ed esterni è spiegato abbastanza chiaramente.

Una questione fondamentale è decidere quale parte controlla l'iterazione, l'iteratore o il client che utilizza l'iteratore.Quando il client controlla l'iterazione, l'iteratore è chiamato iteratore esterno e quando l'iteratore lo controlla, l'iteratore è un iteratore interno.I client che utilizzano un iteratore esterno devono avanzare nell'attraversamento e richiedere esplicitamente l'elemento successivo all'iteratore.Al contrario, il client affida a un iteratore interno un'operazione da eseguire e l'iteratore applica tale operazione a ogni elemento....

Gli iteratori esterni sono più flessibili degli iteratori interni.È facile confrontare due raccolte per verificarne l'uguaglianza con un iteratore esterno, ad esempio, ma è praticamente impossibile con gli iteratori interni...D'altro canto, gli iteratori interni sono più facili da usare perché definiscono la logica dell'iterazione.

Per un esempio di come funzionano gli iteratori interni, vedere Ruby's Enumerable API, che ha metodi di iterazione interni come each.In Ruby, l'idea è di passare un blocco di codice (cioèuna chiusura) a un iteratore interno in modo che una raccolta possa occuparsi della propria iterazione.

è importante mantenere la raccolta separata dal puntatore.l'iteratore punta a un punto specifico in una raccolta e quindi non è parte integrante della raccolta.in questo modo, ad esempio, puoi utilizzare più iteratori sulla stessa raccolta.

lo svantaggio di questa separazione è che l'iteratore non è a conoscenza delle modifiche apportate alla raccolta su cui esegue l'iterazione.quindi non è possibile modificare la struttura della raccolta e aspettarsi che l'iteratore continui il suo lavoro senza "reclami".

Usando il Iterator L'interfaccia consente a qualsiasi classe che implementa i suoi metodi di agire come iteratori.La nozione di interfaccia in Java consiste nell'avere, in un certo senso, l'obbligo contrattuale di fornire determinate funzionalità in una classe che implements l'interfaccia, per agire nel modo richiesto dall'interfaccia.Poiché gli obblighi contrattuali devono essere rispettati per essere una classe valida, altre classi che vedono la classe implements l'interfaccia e quindi rassicurato nel sapere che la classe avrà quelle determinate funzionalità.

In questo esempio, invece di implementare i metodi (hasNext(), next(), remove()) nel LinkedList classe stessa, il LinkedList la classe lo dichiarerà implements IL Iterator interfaccia, quindi gli altri sanno che il file LinkedList può essere utilizzato come iteratore.A sua volta, il LinkedList la classe implementerà i metodi da Iterator interfaccia (es hasNext()), quindi può funzionare come un iteratore.

In altre parole, implementare un'interfaccia è una nozione di programmazione orientata agli oggetti per far sapere agli altri che una determinata classe ha le carte in regola per essere ciò che afferma di essere.

Questa nozione viene applicata disponendo di metodi che devono essere implementati da una classe che implementa l'interfaccia.Ciò garantisce che le altre classi che desiderano utilizzare la classe che implementa il file Iterator interfaccia che avrà effettivamente metodi che gli Iteratori dovrebbero avere, come ad esempio hasNext().

Inoltre, va notato che poiché Java non ha ereditarietà multipla, è possibile utilizzare l'interfaccia per emulare tale funzionalità.Implementando più interfacce, è possibile avere una classe che è una sottoclasse per ereditare alcune funzionalità, ma anche "ereditare" le funzionalità di un'altra implementando un'interfaccia.Un esempio potrebbe essere, se volessi avere una sottoclasse di LinkedList classe chiamata ReversibleLinkedList che potrebbe scorrere in ordine inverso, potrei creare un'interfaccia chiamata ReverseIterator e imporre che fornisca a previous() metodo.Dal momento che LinkedList già implementa Iterator, il nuovo elenco reversibile avrebbe implementato sia il Iterator E ReverseIterator interfacce.

Puoi leggere ulteriori informazioni sulle interfacce da Cos'è un'interfaccia? dal tutorial Java di Sun.

È possibile utilizzare più istanze di un interatore contemporaneamente.Avvicinateli come cursori locali per i dati sottostanti.

A proposito:Privilegiare le interfacce rispetto alle implementazioni concrete perde l'accoppiamento

Cerca il modello di progettazione dell'iteratore e qui: http://en.wikipedia.org/wiki/Iterator

Perché potresti ripetere qualcosa che non è una struttura dati.Diciamo che ho un'applicazione in rete che estrae risultati da un server.Posso restituire un wrapper Iterator attorno a questi risultati e trasmetterli in streaming attraverso qualsiasi codice standard che accetta un oggetto Iterator.

Consideralo una parte fondamentale di un buon progetto MVC.I dati devono provenire dal Modello (es.struttura dei dati) alla vista in qualche modo.L'utilizzo di un Iterator come intermediario garantisce che l'implementazione del modello non venga mai esposta.Potresti mantenere una LinkedList in memoria, estrarre informazioni da un algoritmo di decrittazione o eseguire il wrapper di chiamate JDBC.Semplicemente non ha importanza per la vista, perché la vista si preoccupa solo dell'interfaccia Iterator.

Un articolo interessante che discute i pro e i contro dell'utilizzo degli iteratori:

http://www.sei.cmu.edu/pacc/CBSE5/Sridhar-cbse5-final.pdf

Penso che sia semplicemente una buona pratica OO.Puoi avere codice che si occupa di tutti i tipi di iteratori e ti dà anche l'opportunità di creare le tue strutture dati o semplicemente classi generiche che implementano l'interfaccia dell'iteratore.Non devi preoccuparti del tipo di implementazione che c'è dietro.

Solo M2C, se non lo sapevi:puoi evitare di utilizzare direttamente l'interfaccia dell'iteratore in situazioni in cui il per ciascuno il ciclo sarà sufficiente.

In definitiva, perché Iterator acquisisce un'astrazione di controllo applicabile a un gran numero di strutture dati.Se sei interessato alla teoria delle categorie, potresti rimanere a bocca aperta leggendo questo articolo: L'essenza del modello iteratore.

Bene, sembra che il primo punto dell'elenco consenta alle applicazioni multi-thread (o a thread singolo se sbagli) di non dover bloccare la raccolta per violazioni della concorrenza.In .NET, ad esempio, non è possibile enumerare e modificare una raccolta (o un elenco o qualsiasi IEnumerable) contemporaneamente senza bloccare o ereditare da IEnumerable e sovrascrivere i metodi (otteniamo eccezioni).

Iterator aggiunge semplicemente un modo comune di esaminare una raccolta di elementi.Una delle funzionalità interessanti è i.remove() in cui puoi rimuovere elementi dall'elenco su cui stai eseguendo l'iterazione.Se provassi semplicemente a rimuovere elementi da un elenco normalmente, si avrebbero effetti strani o lancio ed eccezione.

L'interfaccia è come un contratto per tutte le cose che la implementano.In pratica stai dicendo...tutto ciò che implementa un iteratore avrà sicuramente questi metodi che si comportano allo stesso modo.Puoi anche usarlo per passare i tipi di iteratore se questo è tutto ciò che ti interessa gestire nel tuo codice.(potresti non interessarti di che tipo di elenco si tratta..vuoi solo passare un Iterator) Potresti inserire tutti questi metodi in modo indipendente nelle raccolte ma non garantisci che si comportino allo stesso modo o che abbiano lo stesso nome e le stesse firme.

Gli iteratori sono uno dei tanti modelli di progettazione disponibili in Java.I modelli di progettazione possono essere pensati come elementi costitutivi, stili, utilizzo del codice/struttura convenienti.

Per saperne di più sul modello di progettazione Iterator, consulta questo sito Web che parla di Iterator e di molti altri modelli di progettazione.Ecco uno snippet dal sito su Iterator: http://www.patterndepot.com/put/8/Behavioral.html

L'iteratore è uno dei più semplici e più frequentemente utilizzati dei modelli di progettazione.Il modello iteratore consente di spostarti attraverso un elenco o una raccolta di dati utilizzando un'interfaccia standard senza dover conoscere i dettagli delle rappresentazioni interne di tali dati.Inoltre, è possibile definire anche iteratori speciali che eseguono alcuni elementi speciali e restituiti solo della raccolta dei dati.

Gli iteratori possono essere utilizzati contro qualsiasi tipo di raccolta.Consentono di definire un algoritmo rispetto a una raccolta di elementi indipendentemente dall'implementazione sottostante.Ciò significa che puoi elaborare un elenco, un set, una stringa, un file, un array, ecc.

Tra dieci anni potrai modificare l'implementazione dell'elenco in un'implementazione migliore e l'algoritmo continuerà a funzionare senza problemi.

Iterator è utile quando hai a che fare con raccolte in Java.

Utilizzo Per ciascuno loop(Java1.5) per scorrere una raccolta, un array o un elenco.

L'interfaccia java.util.Iterator viene utilizzata in Java Collections Framework per consentire la modifica della raccolta mentre si sta ancora scorrendo su di essa.Se vuoi semplicemente eseguire l'iterazione in modo pulito su un'intera raccolta, utilizza invece un for-each, ma un vantaggio degli Iteratori è la funzionalità che ottieni:un'operazione opzionale di rimozione(), e ancora migliore per l'interfaccia List Iterator, che offre anche operazioni add() e set().Entrambe queste interfacce ti consentono di scorrere una raccolta e di modificarla strutturalmente allo stesso tempo.Provare a modificare una raccolta durante l'iterazione con un for-each genererebbe un'eccezione ConcurrentModificationException, in genere perché la raccolta viene modificata inaspettatamente!

Dai un'occhiata alla classe ArrayList

Ha 2 lezioni private al suo interno (classi interne) chiamate ITR e ListITR

Implementano rispettivamente le interfacce Iterator e ListIterator

classe pubblica ArrayList.....{ //classe che racchiude

  private class Itr implements Iterator<E> {

        public E next() {
            return ArrayList.this.get(index++); //rough, not exact
        }

        //we have to use ArrayList.this.get() so the compiler will
        //know that we are referring to the methods in the 
        //enclosing ArrayList class

        public void remove() {
            ArrayList.this.remove(prevIndex);
        }

        //checks for...co mod of the list
        final void checkForComodification() {  //ListItr gets this method as well
             if (ArrayList.this.modCount != expectedModCount) { 
                 throw new ConcurrentModificationException();
             }
        }
  }

  private class ListItr extends Itr implements ListIterator<E> {
         //methods inherted....
        public void add(E e) {
            ArrayList.this.add(cursor, e);
        }

        public void set(E e) {
            ArrayList.this.set(cursor, e);
        }
  }

}

Quando si chiamano i metodi iterator () e listerator (), restituiscono una nuova istanza della classe privata ITR o ListITR e, poiché queste classi interne sono "all'interno" della classe ArrayList di rallenta , a meno che non si modifichi l'elenco contemporaneamente (in concomitanza) tramite i metodi set () aggiungi () o rimuovi () della classe ArrayList.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top