Funzionamento iteratori

di il
57 risposte

57 Risposte - Pagina 2

  • Re: Funzionamento iteratori

    Pensavo inizialmente di scansionare gli elementi dell'array mediante l'iteratore e poi fare un controllo se l'elemento arr fosse true o false in modo probabilmente insensato... lasciamo stare.

    Quindi se adesso ho capito :

    
    private class MyIter implements Iterator {
       
       int index = 0;
       
       public boolean hasNext() { 
          return ((index < arr.length) && (arr[index] == true)); //verifica se l'elemento index è true 
       }
          
       public int next() {
          if (hasNext())
        	  return index++; //restituisce l'indice dell'elemento
       }
       
       public void remove() {
    	   
       }
       
    }
    
    
  • Re: Funzionamento iteratori

    No, non è sufficiente. Devi considerare che i true possono essere sparpagliati e distanti tra di loro.

    Se l'array contiene

    F F T F F T T F F F T

    Devi "saltare" al 2, poi al 5, 6, poi al 10. E per far questo è necessaria un po' di "logica".
  • Re: Funzionamento iteratori

    Mi spiace ma non mi è chiaro. Non ho capito come faccio a “saltare” dato che non so a priori dove si trovano i true e quindi dovrei scansionare gli elementi uno alla volta.

    Mi viene da pensare in quest'altro modo:
    
    private class MyIter implements Iterator {
       
       int index = 0;
       
       public boolean hasNext() { 
          return (index < arr.length);
       }
           
       public int next() {
          while (hasNext()) {
        	  if(arr[index]==false)
        		  index++;
        	  else
        		  return index++; 
          }
          //gestione eccezione throw new NoSuchElementException();
       }   
          
       
       public void remove() {
    	   
       }
       
    }
    
    hasNext() verifica se index non supera la dimensione dell'array, se ok restituisce “true”, altrimenti “false”.
    Il metodo next() verifica il risultato di hasNext(), itera finché non trova il primo “true” restituendo index (lo incrementa di 1), se il valore dell'elemento è “false” incrementa index passando di nuovo al controllo del while.
  • Re: Funzionamento iteratori

    Paolinos ha scritto:


    Non ho capito come faccio a “saltare” dato che non so a priori dove si trovano i true e quindi dovrei scansionare gli elementi uno alla volta.

    Mi viene da pensare in quest'altro modo:
    No, è comunque inappropriato, in particolare il hasNext.

    Io ti do un consiglio: fai un metodo privato nel tuo MyIter (così è ad uso e consumo solo dei hasNext/next) che dato il index di istanza va a cercare l'indice del prossimo true (che può anche essere già all'indice di index) e lo restituisce, altrimenti restituisce -1 (=non trovato).
    A quel punto usare questo metodo dai hasNext/next è di una banalità disarmante.
  • Re: Funzionamento iteratori

    Ci ho riflettuto, spero di aver capito:
    
    private class MyIter implements Iterator {
       
       int index = 0;
       
       private int find(int i) {
    	   while(i < arr.length) { 
    		   if(arr[i] == true)
    			   return i++;
    	       i++;
    	   }
    	   return -1;
       }
       
       public boolean hasNext() { 
          return (find(index) != -1);
       }
           
       public int next() {
          if(!hasNext()) throw new NoSuchElementException();
          return index;
       }   
            
       public void remove() {
    	   
       }
      
    }
    
  • Re: Funzionamento iteratori

    Come si direbbe in un gioco: "fuocherello".
    Hai compreso il senso del "find" privato che dicevo io ma
    1) il find sarebbe leggermente migliorabile (e nota che il ++ post-incremento nel return non serve a nulla.
    2) il find va usato anche nel next() (e può sostituire il hasNext che stai usando ora)


    Il hasNext di per sé è corretto.


    P.S. Se intendi implementare il remove() pensa BENE a come gestire il index di MyIter.
    Da specifiche di Iterator, il remove() è invocabile UNA volta sola DOPO ogni next().
  • Re: Funzionamento iteratori

    Quindi:
    
    private class MyIter implements Iterator {
       
       int index = 0;
       
       private int find(int i) {
          while(i < arr.length) { 
             if(arr[i] == true)
                return i; //<-------------------------modificato
              i++;
          }
          return -1;
       }
       
       public boolean hasNext() { 
          return (find(index) != -1);
       }
           
       public int next() {
          if(!hasNext()) throw new NoSuchElementException();
          return find(index); //<---------------------modificato
       }   
            
       public void remove() {
          
       }
      
    }
    
    Devo capire come migliorare find().
    Pensavo ... posso utilizzare una variabile ("conta") che conta il numero di "true" nella classe BoolSet (conta++ ad ogni operazione di put, conta-- quando viene "eliminato" l'elemento cioè viene impostato a "false") in modo da terminare l'iterazione quando i > conta, quindi risparmiare eventualmente delle iterazioni.
    
       private int find(int i) {
          while((i < arr.length) && (i <= conta)) { 
             if(arr[i] == true)
                return i;
              i++;
          }
          return -1;
       }
    
  • Re: Funzionamento iteratori

    Paolinos ha scritto:


    Pensavo ... posso utilizzare una variabile ("conta") che conta il numero di "true" nella classe BoolSet
    No, non serve un "conta" del genere.

    E comunque il remove() va invocato dopo aver fatto un next(). E nel tuo caso il remove dovrebbe semplicemente andare a mettere false al index che il next() ha trovato. Ma questo vuol dire che terminato il next(), il index in MyIter deve essere ancora quello in cui next() ha trovato il true!
    Ora ... questione: come farebbe allora next() a far andare sempre più avanti? Semplicemente c'è da ragionare di più su come gestire il index in MyItem.

    P.S. il tuo next() non è ancora ok. hasNext() NON deve toccare nulla nello stato di MyIter (ovvero NON deve aggiornare la variabile di istanza index). Ma next() sì, lo DEVE aggiornare. Altrimenti, ripeto, come si fa ad andare avanti da un next() al successivo??
  • Re: Funzionamento iteratori

    Allora:

    hasNext() cerca il prossimo true (utilizza il metodo find()) -----> non modifica index
    
    public boolean hasNext() { 
          return (find(index) != -1);
       }
    
    next() verifica l'esistenza del prossimo true (se c'è) e ne restituisce l'indice (index). Dopo incrementa index per andare da un next al successivo
    
       public int next() {
          if(!hasNext()) throw new NoSuchElementException();
          return find(index++);
       } 
    

    Per quanto riguarda remove() posso evitare di implementarlo? Nella classe BoolSet devo implementare il metodo public boolean remove(int elem) dove elem è l'intero da eliminare (restituisce true se è presente, false altrimenti).
  • Re: Funzionamento iteratori

    Ops mi sono reso conto di un errore... rivedo quello che ho scritto sopra
  • Re: Funzionamento iteratori

    Allora:

    hasNext() cerca il prossimo true (utilizza il metodo find()) -----> non modifica index
    
       public boolean hasNext() { 
          return (find(index) != -1);
       }
    


    next() verifica l'esistenza del prossimo true (se c'è) e ne restituisce l'indice (index). Dopo incrementa index per andare da un next al successivo
    
       public int next() {
          if(!hasNext()) throw new NoSuchElementException();
          return find(index++);   //restituisce l'indice e aggiorna index all'elemento successivo
       } 
    
    
    private int find(int i) {
          while(i < arr.length) { 
             if(arr[i] == true) {
            	 index=i; //aggiorno il valore di index
                return i; 
             }   
             i++;
          }
          return -1;
       }
    

    Per quanto riguarda remove() posso evitare di implementarlo? Nella classe BoolSet devo implementare il metodo public boolean remove(int elem) dove elem è l'intero da eliminare (restituisce true se è presente, false altrimenti).
  • Re: Funzionamento iteratori

    Paolinos ha scritto:


    next() verifica l'esistenza del prossimo true (se c'è) e ne restituisce l'indice (index). Dopo incrementa index per andare da un next al successivo
    
       public int next() {
          if(!hasNext()) throw new NoSuchElementException();
          return find(index++);   //restituisce l'indice e aggiorna index all'elemento successivo
       } 
    
    Ti ho già detto in precedenza che nel next() NON è più strettamente necessario il hasNext(). Ora hai il find() !

    E comunque se vorrai implementare il remove del Iterator, quel index++ è un problema.

    Paolinos ha scritto:


    
    private int find(int i) {
          while(i < arr.length) { 
             if(arr[i] == true) {
            	 index=i; //aggiorno il valore di index
                return i; 
             }   
             i++;
          }
          return -1;
       }
    
    il find NON deve affatto andare a toccare il index.

    Paolinos ha scritto:


    Per quanto riguarda remove() posso evitare di implementarlo?
    Non dipende da me, non lo so ... dipende dai requisiti che ti sono, credo, stati dati per questa "esercitazione". Il remove del Iterator di per sé non è una operazione fondamentale, può anche essere "non supportata" (con una bella UnsupportedOperationException).

    Paolinos ha scritto:


    Nella classe BoolSet devo implementare il metodo public boolean remove(int elem) dove elem è l'intero da eliminare (restituisce true se è presente, false altrimenti).
    E va bene.
  • Re: Funzionamento iteratori

    andbin ha scritto:


    il find NON deve affatto andare a toccare il index
    Ti ho già detto in precedenza che nel next() NON è più strettamente necessario il hasNext(). Ora hai il find() !
    Si vero mi sono distratto , purtroppo sto facendo diverse cose "assieme" e il tempo è oltretutto poco ...

    Spero con questa di aver risolto questo punto:
    
    private class MyIter implements Iterator {
       
       int index = 0;
       
       private int find(int i) {
          while(i < arr.length) { 
             if(arr[i] == true) {
                return i; 
             }   
             i++;
          }
          return -1;
       }
       
       public boolean hasNext() { 
          return (find(index) != -1);
       }
           
       public int next() {
    	   index = find(index);
          if(index == -1) throw new NoSuchElementException();
          return index++;
       }   
            
       public void remove() { //non viene implementato
    	   throw new UnsupportedOperationException();
       }
      
    }
    
  • Re: Funzionamento iteratori

    Paolinos ha scritto:


    Spero con questa di aver risolto questo punto:
    Se Iterator non è parametrizzato, il next() deve avere Object come tipo di ritorno.

    A parte questo, è funzionalmente corretto (chiaramente il remove non è supportato ma può essere ok).
  • Re: Funzionamento iteratori

    Se Iterator non è parametrizzato, il next() deve avere Object come tipo di ritorno.
    Se Iterator viene parametrizzato in questo modo:
    
    public Iterator<Integer> iterator() {
       return new MyIter();
    }
    
    sarebbe corretto:
    
    private class MyIter implements Iterator {
    
    	public int next() { 
    		...
    	}
    	
    	...
    }
    
    L'interfaccia è corretta così:
    
    public interface Ins<T> extends Iterable<T>, Cloneable {
    	...
    	Iterator iterator();
    }
    
Devi accedere o registrarti per scrivere nel forum
57 risposte