Visualizzazione dei risultati da 1 a 5 su 5
  1. #1

    come fare un iteratore??

    Allora,
    Ho una interfaccia che estende iterable, poi ho unaq classe concreta che implementa l'interfaccia.

    adesso devo implementare il metodo:

    /**
    * Restituisce un iteratore per scandire gli elementi dell’insieme in ordine
    * crescente, il metodo remove non è implementato
    *
    * @return l'iteratore
    */
    Iterator iterator();

    Io ho fatto così:

    public Iterator iterator() {
    return new ArrIterator(this);
    }

    Non riesco a fare il costruttore dell'iteratore...voi avete qualche idea??
    Io ho assegnato a una variabile di tipo array di int l' insieme che gli passo..e poi???

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: come fare un iteratore??

    Originariamente inviato da mrjava87
    Non riesco a fare il costruttore dell'iteratore...voi avete qualche idea??
    Innanzitutto la classe "concreta" che implementa l'iteratore tipicamente non la si fa come classe "pubblica" ovvero accessibile a chiunque. E sempre tipicamente la si implementa come inner class (regular o anonymous) privata all'interno della classe che gestisce la "collezione".
    Questo per motivi che possono essere facilmente intuibili: l'iteratore deve essere molto "intimo" con la struttura dati interna della collezione. Struttura quindi che solo la collezione e l'iteratore devono poter conoscere e usare direttamente.

    Ecco un esempio banale/minimale:

    codice:
    import java.util.*;
    
    public class Prova {
        public static void main(String[] args) {
            FixedArray<String> ba = new FixedArray<String>(10);
            ba.add("hello");
            ba.add("world");
    
            Iterator<String> it = ba.iterator();
            while (it.hasNext()) {
                System.out.println(it.next());
            }
        }
    }
    
    
    class FixedArray<E> {
        private Object[] elements;
        private int size;
    
        public FixedArray(int capacity) {
            elements = new Object[capacity];
        }
    
        public void add(E e) {
            if (size < elements.length) {
                elements[size++] = e;
            }
        }
    
        public Iterator<E> iterator() {
            return new FixedArrayIterator();
        }
    
    
        private class FixedArrayIterator implements Iterator<E> {
            private int cursor = 0;
    
            public boolean hasNext() {
                return cursor < size;
            }
    
            @SuppressWarnings("unchecked")
            public E next() {
                if (cursor < size) {
                    return (E) elements[cursor++];
                } else {
                    throw new NoSuchElementException();
                }
            }
    
            public void remove() {
                throw new UnsupportedOperationException();
            }
        }
    }
    La classe FixedArrayIterator che implementa l'iteratore è una "regular" inner class ed è privata. Non avrebbe molto senso renderla pubblica. Essendo una inner class ha dei vantaggi, ovvero è in grado di accedere ai campi della classe contenitore, cioè la collezione. E nel caso sopra non c'è nemmeno bisogno che FixedArrayIterator abbia un costruttore esplicito. C'è un solo campo 'cursor' inizializzato a 0. E questo è sufficiente.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3

    Re: Re: come fare un iteratore??

    Originariamente inviato da andbin
    Innanzitutto la classe "concreta" che implementa l'iteratore tipicamente non la si fa come classe "pubblica" ovvero accessibile a chiunque. E sempre tipicamente la si implementa come inner class (regular o anonymous) privata all'interno della classe che gestisce la "collezione".
    Questo per motivi che possono essere facilmente intuibili: l'iteratore deve essere molto "intimo" con la struttura dati interna della collezione. Struttura quindi che solo la collezione e l'iteratore devono poter conoscere e usare direttamente.

    Ecco un esempio banale/minimale:

    codice:
    import java.util.*;
    
    public class Prova {
        public static void main(String[] args) {
            FixedArray<String> ba = new FixedArray<String>(10);
            ba.add("hello");
            ba.add("world");
    
            Iterator<String> it = ba.iterator();
            while (it.hasNext()) {
                System.out.println(it.next());
            }
        }
    }
    
    
    class FixedArray<E> {
        private Object[] elements;
        private int size;
    
        public FixedArray(int capacity) {
            elements = new Object[capacity];
        }
    
        public void add(E e) {
            if (size < elements.length) {
                elements[size++] = e;
            }
        }
    
        public Iterator<E> iterator() {
            return new FixedArrayIterator();
        }
    
    
        private class FixedArrayIterator implements Iterator<E> {
            private int cursor = 0;
    
            public boolean hasNext() {
                return cursor < size;
            }
    
            @SuppressWarnings("unchecked")
            public E next() {
                if (cursor < size) {
                    return (E) elements[cursor++];
                } else {
                    throw new NoSuchElementException();
                }
            }
    
            public void remove() {
                throw new UnsupportedOperationException();
            }
        }
    }
    La classe FixedArrayIterator che implementa l'iteratore è una "regular" inner class ed è privata. Non avrebbe molto senso renderla pubblica. Essendo una inner class ha dei vantaggi, ovvero è in grado di accedere ai campi della classe contenitore, cioè la collezione. E nel caso sopra non c'è nemmeno bisogno che FixedArrayIterator abbia un costruttore esplicito. C'è un solo campo 'cursor' inizializzato a 0. E questo è sufficiente.
    Scusa andbin, ti faccio una domandina:

    Ma perché hai dichiarato come contenitore "fisico" degli oggetti della tua collezione una array di Object piuttosto che un array di E??

    Tutto sommato ormai la tua struttura sfrutta i generics, tanto vale usarli anche per istanziare nel modo corretto anche il tipo dell'array no?? Tanto è vero che tu poi nel metodo next() dell'iteratore per restituire un oggetto di tipo E tu fai un cast dell'object che prelevi dall'array...
    Allora mi chiedo, tu conosci qualcosa che io non so che detta questa scelta (es, che ne so, discorsi di prestazioni) oppure non c'è un motivo particolare???

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: Re: Re: come fare un iteratore??

    Originariamente inviato da canemacchina
    Ma perché hai dichiarato come contenitore "fisico" degli oggetti della tua collezione una array di Object piuttosto che un array di E??
    Perché "E" è un type variable e sebbene si possa dichiarare:

    private E[] elements;

    in teoria avrei poi dovuto fare nel costruttore:

    elements = new E[capacity];

    Ma questo NON è permesso. "E" non è un nome di una classe!!!! Non si sa che cosa è!!!

    Generics e array è un mix che dà questi problemi. Non si possono creare array di tipi non reifiable ("reificabili").

    Ci sono 2 strade per risolvere la cosa:

    -------------
    A) Dichiarare un array E[] e poi nel costruttore fare:

    elements = (E[]) new Object[capacity];

    Questo è un cast "unchecked" che provoca un warning che si può sopprimere con la apposita annotazione.
    -------------
    B) Dichiarare un array Object[] e poi nel costruttore fare:

    elements = new Object[capacity];

    e fare dei cast a E dove necessario (generalmente dove si deve far ritornare un elemento della collezione). Questi cast sono nuovamente cast "unchecked" e anche qui si può sopprimere il warning.
    -------------

    Quale delle due scegliere??? Generalmente è una questione di "gusti" ... entrambe funzionano. Con la prima strada si ha 1 solo cast unchecked, con la seconda tanti dove necessario avere un "E".
    Ma c'è da tenere presente una cosa: detto in generale è più rischioso sopprimere un warning su un cast ad un array (E[]) piuttosto che ad un tipo scalare (E) ("rischioso" nel senso che si deve sapere bene che cosa si sta facendo .... nel caso sopra ci si può rendere facilmente conto che il cast non è "pericoloso" a patto che l'array resti interno e nascosto).

    Le collezioni standard ArrayList e Vector (basate internamente su array) usano la soluzione B, tanto per fare un esempio reale.
    In altre situazioni e dove si dovrebbero fare tanti cast, la soluzione A potrebbe essere più utile.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Azz, mi ero scordato!
    Il bello è che ho pure dovuto sbattere la testa su array e tipi genercis durante un corso all'università. Dannata testa!

    Comunque ok, la questione sulla "rischiosità" del cast non me la ero mai posta... Credo tu abbia ragione!

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.