PDA

View Full Version : [JAVA] Quesito sugli iteratori


D4rkAng3l
12-05-2009, 20:05
Ciao,
studiando Java sono arrivato a vedere gli iteratori...vi faccio qualche domanda relativa ad un esempio giocattolo fatto dalla professoressa.

Da quello che ho capito uso il meccanismo degli iteratori per poter scorrere collezioni di oggetti in modo standard per tutti i tipi di collezioni senza dover scendere a basso livello (per esempio impostando un ciclo per scorrere un array o una lista concatenata).

Così quando progetto una collezione di oggetti posso cacciarci dentro una particolare implementazione dell'interface Iterator e chi userà la classe che implementa quella collezione avrà gratis un modo standard per scorrere la collezione....è giusto come concetto del perchè si usano gli iteratori?

Veniamo all'esempio fatto in classe:

public class CollStr{ // Classe che gestisce una collezione di stringhe

private String[] c; // Variabile di istanza: la collezione di stringhe è gestita banalmente da un array di stringhe
int i;

public CollStr(String str[]){ // COSTRUTTORE
// COSTRUISCE L'ARRAY c CHE IMPLEMENTA LA COLLEZIONE IN QUALCHE MODO
}

private class MioIteratore implements Iterator{ // E' una CLASSE INTERNA che implementa l'interface Iterator

private int dove;

public MioIteratore(){ // COSTRUTTORE MioIterator
dove = 0; // Punta al primo elemento dell'array
}

public Object next(){ // Restituisce l'elemento non ancora estratto
return c[dove];
}

public void remove(){
dove ++; // Non elimina l'oggetto dalla collezione malo rimuove solo dall'iteratore
}

public boolean hasNext{
return dove < c.length; // TRUE se ha un elemento successivo, FALSE se non ce l'ha
}

} // CHIUSURA DELLA CLASSE INTERNA

public Iterator enumera(){ // Metodo che restituisce il riferimento ad un oggetto che implementa Iterator
return new MioIteratore(); // Ritorna il riferimento ad un oggetto di tipo MioIteratore appena creato
}

}


La collezione di stringhe viene banalmente rappresentata tramite un array di stringhe (il costruttore non l'ho scritto perchè tanto ai fini di questo argomento mi interessa poco ora come ora)

Poi voglio munirla di un iteratore per poterla scorrere comodamente in modo standard, allora ci ficco dentro una classe interna che ho chiamato MioIteratore che implementa l'interface Iterator e quindi implementa in modo coerente a com'è rappresentata la collezione tutti i metodi presenti dentro Iterator.

Fin quì tutto ok...

La domanda è la seguente....perchè poi fuori alla classe interna (quindi dentro la classe esterna) la proff ha dichiarato il metodo enumera che di fatto restituisce il riferimento ad un MioIteratore? Per comodità?

Ad esempio nel main se volevo iterare non funzionava comunque se creavo un nuovo oggetto di tipo MioIteratore a mano? Oppure non lo vedrei perchè è nella classe interna e quindi devo usare per forza il metodo enumera che è nella classe esterna che a sua volta può comunicare con la classe interna?

Spero di essere stato abbastanza chiaro...

Grazie
Andrea

wingman87
12-05-2009, 21:21
MioIteratore è una classe interna privata, quindi dall'esterno non sarebbe possibile instanziarla e neanche richiamarne i suoi metodi. Grazie al metodo enumera e allo sfruttamento dell'override è invece possibile: notare che enumera torna un riferimento a Iterator, quindi dall'esterno farai una cosa del tipo:
CollStr c;
...
Iterator it=c.enumera();
while(it.hasNext()){
String s=it.next();
...
}
Quindi dall'esterno ti sembrerà di usare un Iterator generico ma in realtà starai usando i metodi di MioIteratore.

mostec
12-05-2009, 21:36
credo che il nome più corretto per il metodo enumera() fosse getIterator().
questo metodo serve per rendere disponibile l'iteratore all'esterno della classe.

come vedi la classe MioIteratore è dichiarata private all'interno della classe della classe CollStr. Al di fuori di essa quindi non è visibile, di conseguenza non sarebbe istanziabile.
Questo non è l'unico problema. Anche se la classe MioIteratore fosse stata public sarebbe comunque concettualmente sbagliato istanziarla al di fuori della collezione.
Se noti bene MioIteratore in diversi metodi legge informazioni dall'array di stringhe c di CollStr. Se tu riuscissi a instanziare un oggetto MioIteratore al di fuori di un oggetto CollStr otterresti un iteratore senza riferimenti all'array da scorrere. Ovviamente non servirebbe a nulla.


Spero di esser stato chiaro.
Ciao.

banryu79
13-05-2009, 08:29
Scusa,
ma sei sicuro che il il metodo next() dell'iteratore nel codice di esempio postato sia implementato correttamente?

Perchè cos'ì com'è restituisce l'oggetto all'indice corrente 'dove', ma non incrementa l'indice stesso.

Per incrementare l'indice nel tuo iteratore attualmente si è costretti a chiamare il metodo remove(), che non ritorna niente.

Della serie che, per scandire la collezione riportata nel codice di esempio sarei costretto fare così:

CollStr c;
...
Iterator it=c.enumera();
while(it.hasNext())
{
String s = it.next();
it.remove(); // neccessario per incrementare l'indice interno dell'iteratore
// ...
}

D4rkAng3l
13-05-2009, 08:53
Scusa,
ma sei sicuro che il il metodo next() dell'iteratore nel codice di esempio postato sia implementato correttamente?

Perchè cos'ì com'è restituisce l'oggetto all'indice corrente 'dove', ma non incrementa l'indice stesso.

Per incrementare l'indice nel tuo iteratore attualmente si è costretti a chiamare il metodo remove(), che non ritorna niente.

Della serie che, per scandire la collezione riportata nel codice di esempio sarei costretto fare così:

CollStr c;
...
Iterator it=c.enumera();
while(it.hasNext())
{
String s = it.next();
it.remove(); // neccessario per incrementare l'indice interno dell'iteratore
// ...
}


Esattamente...sul libro di testo e sugli appunti della professoressa dice che grazie agli iteratori ho un modo standard per operare sulle collezioni e che questo modo standard è sempre il seguente:


public class Test{
public static void main(String[] args){

int k;
CollStr x = new CollStr(....); // Crea in qualche modo la collezione di stringhe
String s;

Iterator it; // Dichiaro una variabile di tipo Iterator
it = x.enumera(); // Crea il corretto iteratore per la collezione x

while(it.hasNext()){ // Finchè nella collezione ci sono ancora elementi su cui iterare
s = (String) it.next(); // Metti in s la stringa corrente
// USA S IN QUALCHE MODO;
it.remove(); // Passa al successivo elemento rimuovendo quello corrente dall'iteratore (non dalla collezione)
}
}
}


Ciao
Andrea