Funzionamento iteratori

di il
57 risposte

Funzionamento iteratori

Buonasera a tutti, devo risolvere un esercizio in java che fa uso di iteratori ecc. Dato che prima devo capire come utilizzarli ho provato con un semplice esempio che però mi evidenzia degli errori nella riga:
Iterator iter = A.iterator();
- Iterator is a raw type. References to generic type Iterator<E> should be parameterized
- Cannot invoke iterator() on the array type boolean[]

Codice:

import java.util.Iterator;

public class Itera {

	public static void main(String[] args) {
		
		boolean A[] = new boolean[10]; //array di booleani
	    
       	Iterator iter = A.iterator(); //utilizzo un oggetto di tipo Iterator
       	while (iter.hasNext()) {
           	 boolean val = (boolean) iter.next();
           	 System.out.println(val);
      	}		
	}	
}
Grazie mille

57 Risposte

  • Re: Funzionamento iteratori

    Paolinos ha scritto:


    		boolean A[] = new boolean[10]; //array di booleani
    	    
           	Iterator iter = A.iterator(); //utilizzo un oggetto di tipo Iterator
    Gli array NON hanno un iteratore. Gli iteratori li hanno le "collection" del framework: ArrayList, Vector, HashSet, ecc...
  • Re: Funzionamento iteratori

    Buonasera andbin, grazie della risposta, ho pensato anch'io a quello che hai scritto ma volevo una conferma.

    A questo punto avrei un problema col progetto da sviluppare. In pratica ho un'interfaccia Ins che estende le interfacce Clonable e Iterable, la quale contiene i metodi (clear, isempty, max, put, remove, clone, unione, ecc)

    Adesso devo creare la classe BoolSet che da un'implementare di Ins come array di booleani e non posso utilizzare strutture delle API di java (limite progetto).

    Uno dei metodi da implementare (oltre quelli sopra citati) è “public Iterator iter()” il quale deve restituire un iteratore che scandisce gli elementi dell'insieme in ordine crescente, da utilizzare all'interno dei metodi.

    La classe Test ce l'ho già:
    
    // ...
    public static void main(String[] args) {
    
    	Ins insieme1 = new BoolSet; //crea insieme1 (inizialmente vuoto)
    	insieme1.put(3); //aggiunge l'elemento 3
    	insieme1.put(4);
    	insieme1.put(2);
    	insieme1.put(7);
    	
    	Ins insieme2 = new BoolSet; //crea insieme2
    	insieme1.put(5);
    	insieme1.put(2);
    	
    	//stampa contenuto insiemi
    	system.out.println(insieme1);
    	system.out.println(insieme2);
    
    	ins1_clone = (Ins) insieme1.clone(); //clone: metodo che clona l'insieme 
    
    	ins1_clone.union(insieme2); //union: metodo che restituisce l'unione tra i due insiemi
    	
    	//... seguono le operazioni intersez., differenza, ecc
    
    
    Hai qualche consiglio da darmi o idea in merito. Grazie
  • Re: Funzionamento iteratori

    Paolinos ha scritto:


    Adesso devo creare la classe BoolSet che da un'implementare di Ins come array di booleani e non posso utilizzare strutture delle API di java (limite progetto).
    Ok, assolutamente "comprensibile" (per ovvi motivi "didattici", immagino)

    Paolinos ha scritto:


    Uno dei metodi da implementare (oltre quelli sopra citati) è “public Iterator iter()”
    public Iterator<T> iterator()

    per essere precisi. E dato che il tuo BoolSet è specifico per boolean, allora invece di <T> sarà da specificare <Boolean>

    (nota che in teoria, la tua interfaccia Ins dovrebbe essere "generica", cioè Ins<T>. E poi nel tuo BoolSet vai a "fissare" la parametrizzazione facendo implements Ins<Boolean> )

    Paolinos ha scritto:


    il quale deve restituire un iteratore che scandisce gli elementi dell'insieme in ordine crescente, da utilizzare all'interno dei metodi.
    Vuol dire che devi implementare concretamente la interfaccia Iterator. Nelle collezioni standard di Java l'iteratore tipicamente si implementa come inner-class privata (non visibile all'esterno) dentro la collezione. Dovrai creare quindi una classe es. MyIterator che implementa Iterator<Boolean> e in cui dovrai definire i tre metodi: hasNext(), next() e remove()

    P.S. cerca anche sul forum, perché sono sicuro che se ne è già parlato di questo.

    Vedi es. qui:
    https://www.iprogrammatori.it/forum-programmazione/java/richiesta-aiuto-per-risolvere-questo-esercizio-t31573.html
  • Re: Funzionamento iteratori

    Grazie delle dritte andbin

    Per quanto riguarda l'array di booleani, come dovrei dichiararlo se non posso "private boolean[] A" all'interno della classe BoolSet, per rispettare la specifica.

    Grazie ancora

    PS: ho trovato nel forum una vecchia discussione, presumo il mio stesso problema, purtroppo nessun aiuto
  • Re: Funzionamento iteratori

    Paolinos ha scritto:


    Per quanto riguarda l'array di booleani, come dovrei dichiararlo se non posso "private boolean[] A" all'interno della classe BoolSet, per rispettare la specifica.
    Ti è stato chiesto di definire un BoolSet che si basa su un array di booleani (innanzitutto andrebbe precisato: boolean primitivo o java.lang.Boolean?).

    Se un oggetto BoolSet deve contenere da richiesta un array di boolean, allora CERTO che puoi avere un:

    private boolean[] arr;
    o
    private Boolean[] arr;

    Il punto è che da un array non puoi tirar fuori un Iterator, lo dovresti implementare tu, come ho già anticipato prima (e vedi anche la discussione linkata nel P.S.)

    Discorso diverso se mettessi come campo un List<Boolean> (ma così non è un array, come richiesto) perché da un List PUOI tirar fuori un Iterator. E quindi il iterator() del tuo BoolSet farebbe banalmente un return del Iterator tirato fuori dal iterator() della lista.

    Ora dovresti valutare tu.
  • Re: Funzionamento iteratori

    Ok chiaro
    Domani ci metto mano, adesso sono un po' "cotto"
    Grazie e bonanotte
  • Re: Funzionamento iteratori

    Stamattina, un po' più "fresco", ho riletto la discussione, prestando più attenzione anche a quel main() dove si vede es. insieme1.put(3);

    Credo di aver "equivocato" un po' la tua richiesta, perché inizialmente mi pareva di aver capito un'altra cosa. Da quanto deduco, ti è stato chiesto di implementare sostanzialmente un "bit set" (poi se la classe la chiami BoolSet .. è lo stesso), che contiene un array di boolean ciascuno con un proprio indice che è quello usato da chi usa un oggetto BoolSet.

    In sostanza se fai es.:
    Ins insieme1 = new BoolSet();
    insieme1.put(3);
    insieme1.put(4);
    insieme1.put(2);
    insieme1.put(7);
    Vuol dire rappresentare l'insieme dei valori {3,4,2,7}

    In pratica tu dall'esterno di BoolSet NON vedi dei boolean ma dei numeri. L'array interno di boolean serve solo per fare da "sequenza di bit" per cui un valore es. 3 (correlato al quarto boolean) "c'è" o "non c'è".

    Se è così, (confermamelo!), allora le cose vanno diversamente. Vuol dire che quando andrai ad iterare NON vedrai i boolean ma i numeri. Cioè iterando sul insieme1 dovrai ottenere in sequenza 3 ... 4 ... 2 ... 7

    In tal caso allora:

    a) Il Iterator sarà Iterator<Integer>
    b) quindi public Iterator<Integer> iterator()
    c) vuol anche dire che devi per forza implementare tu l'iteratore. Anche se, per dire, in BoolSet tenessi un List<Boolean>, NON potresti sfruttare il suo iteratore.

    Con questi chiarimenti, verifica bene cosa fare, poi si potrà vedere.
  • Re: Funzionamento iteratori

    Per quanto ho capito se faccio:
    
    Ins insieme1 = new BoolSet();
    insieme1.put(3);
    insieme1.put(4);
    insieme1.put(2);
    insieme1.put(7);
    
    l'array di booleani dovrebbe essere: arr=[ F F T T T F F T ], dove T=true e F=false.

    Quindi mi interessano gli indici degli elementi dell'array o sto dicendo una scemenza? Se l'elemento di indice i contiene true (arr=true) vuol dire che l'intero i appartiene all'insieme.

    Se è corretto devo capire come creare l'iteratore che scorre l'array

    Interfaccia Ins:
    
    import java.util.Iterator;
    
    public interface Ins<T> extends Iterable, Cloneable {
     
    	Iterator iterator();
    
    	//... seguono altri metodi
    
    }
    
    
    Classe BoolSet:
    
    public class BoolSet implements Ins<Boolean> {
    	private boolean[] arr;
    
    	//costruttore
    	public BoolSet() {
    		arr=null;
    	}
    	
    	//controlla se l'insieme è vuoto
    	public boolean isEmpty() {
    		if(arr == null)
    			return true;
    		else
    			return false;
    	}
    	
    	//cancella l'insieme
    	public void clear() {
    		arr=null;
    	}
    	
    	public Iterator<T> iterator() {
    	
    	}
    		
    	// ...
    }
    
  • Re: Funzionamento iteratori

    Paolinos ha scritto:


    Quindi mi interessano gli indici degli elementi dell'array o sto dicendo una scemenza? Se l'elemento di indice i contiene true (arr=true) vuol dire che l'intero i appartiene all'insieme.

    Esatto!!

    Paolinos ha scritto:


    
    import java.util.Iterator;
    
    public interface Ins<T> extends Iterable, Cloneable {
     
    	Iterator iterator();
    
    	//... seguono altri metodi
    }
    
    Se vuoi farlo preciso nei confronti dei generics:
    
    import java.util.Iterator;
    
    public interface Ins<T> extends Iterable<T>, Cloneable {
    }
    E non serve rimettere il iterator() .... proviene già da Iterable!

    Paolinos ha scritto:


    Se è corretto devo capire come creare l'iteratore che scorre l'array
    L'oggetto iteratore deve tenersi l'indice a cui è arrivato.
    Il next() deve andare a cercare il prossimo true (e trovato, restituisci l'indice, aggiornandolo nell'iteratore)
    il hasNext() deve andare a cercare il prossimo true e dire se c'è o no ma senza cambiare nulla.
  • Re: Funzionamento iteratori

    Quindi tolgo la firma del metodo Iterator dall'interfaccia Ins (anche se da progetto non posso modificarla)

    Nella classe BoolSet inserisco il metodo “public Iterator<Integer> iterator()” nel quale richiamo i metodi (next(), hasNext() e remove()) definiti in una nuova classe “public class MyIter implements Iterator<Integer>”.

    Chiedo scusa se per caso ho fatto confusione
  • Re: Funzionamento iteratori

    Paolinos ha scritto:


    Quindi tolgo la firma del metodo Iterator dall'interfaccia Ins (anche se da progetto non posso modificarla)
    Se "non puoi" modificarla .... vabbè, ok

    Paolinos ha scritto:


    Nella classe BoolSet inserisco il metodo “public Iterator<Integer> iterator()” nel quale richiamo i metodi (next(), hasNext() e remove()) definiti in una nuova classe “public class MyIter implements Iterator<Integer>”.
    No, il tuo iterator() farà semplicemente un es.

    return new MyIter();

    tutto qui.

    dove MyIter dovrà essere una tua classe che implementa Iterator e in cui sono definiti e implementati i next/hasNext/remove.
    La classe può benissimo essere una inner-class privata dentro BoolSet (questo perché così hai accesso diretto all'array dei boolean)
  • Re: Funzionamento iteratori

    Ok procedo.

    Grazie
  • Re: Funzionamento iteratori

    Buonasera,

    Ricapitolando nella classe BoolSet tra i metodi ho
    
    public Iterator iterator() {
    	return MyIter();
    }
    
    Oltre ai metodi all'interno sempre della classe BoolSet ho anche la inner-class privata MyIter:
     
    private class MyIter<T> implements Iterator<T> {
    	
    	int index = 0;
    	
    	public boolean hasNext() { 
    		return index < arr.length; 
    	}
    		
    	public T next() {
    		if (!hasNext()) throw new NoSuchElementException();
    		return arr[index++];
    	}
    	
    	public void remove() {
    		throw new UnsupportedOperationException();
    	}
    	
    }
    
    Se è corretto devo dichiarare un l'iteratore all'inizio della classe BoolSet nel seguente modo?
    
    import java.util.Iterator;
    import java.util.NoSuchElementException;
    
    public class BoolSet implements Ins<Boolean> {
       private boolean[] arr;
    	
    	Iterator myIteretor = arr.iterator();
    	
      // ...
    }
    
  • Re: Funzionamento iteratori

    Paolinos ha scritto:


    
    public Iterator iterator() {
    	return MyIter();
    }
    
    Sì, esatto. C'è solo la questione della parametrizzazione, perché ora stai usando Iterator senza parametrizzazione, in pratica come raw-type.
    In teoria dovrebbe essere Iterator<Integer> ma per poter essere tale dovrebbe essere corretta anche la parametrizzazione della interfaccia Iterable.

    Paolinos ha scritto:


    Oltre ai metodi all'interno sempre della classe BoolSet ho anche la inner-class privata MyIter:
     
    private class MyIter<T> implements Iterator<T> {
    	
    	int index = 0;
    	
    	public boolean hasNext() { 
    		return index < arr.length; 
    	}
    		
    	public T next() {
    		if (!hasNext()) throw new NoSuchElementException();
    		return arr[index++];
    	}
    	
    	public void remove() {
    		throw new UnsupportedOperationException();
    	}
    	
    }
    
    No, non esattamente. MyIter NON deve essere (e non ha senso che sia) una classe "generica" (non deve avere <T> ).
    Mentre invece il implements Iterator o lo tieni non parametrizzato (come nel iterator() ) oppure lo parametrizzi con <Integer>

    Inoltre hasNext/next/remove li devi implementare appropriatamente, perché quello che hai scritto NON è sufficiente (e nemmeno sensato) per iterare correttamente sui valori numerici rappresentati dal BoolSet.

    Paolinos ha scritto:


    Se è corretto devo dichiarare un l'iteratore all'inizio della classe BoolSet nel seguente modo?
    
    import java.util.Iterator;
    import java.util.NoSuchElementException;
    
    public class BoolSet implements Ins<Boolean> {
       private boolean[] arr;
    	
    	Iterator myIteretor = arr.iterator();
    	
      // ...
    }
    
    Innanzitutto dovrebbe essere

    public class BoolSet implements Ins<Integer> {

    Il fatto che BoolSet usi internamente un boolean[] è solo un dettaglio interno ma dal main() che avevi postato in precedenza (con quei put(3), put(4) ecc...) se ne deduce che tratta numeri, non boolean.

    Inoltre la riga:

    Iterator myIteretor = arr.iterator();

    semplicemente NON ha senso.
Devi accedere o registrarti per scrivere nel forum
57 risposte