Devo restituire Iterable o Enumeration in Java

2

Per ottenere una migliore immutabilità, la mia API dovrebbe restituire java.lang.Iterable<T> o java.util.Enumeration<E> ? Poiché l'iteratore di Iterable ha un metodo remove () , si potrebbe dire che l'enumerazione è la scelta giusta, ma javadoc dice "Le nuove implementazioni dovrebbero prendere in considerazione l'utilizzo di Iterator di preferenza per Enumerazione" .

Sono a conoscenza di raccolte non modificabili, ma in tal caso ci ritroviamo ancora con raccolte che espongono metodi di aggiunta e rimozione.

Qualche altra opzione in Java?

    
posta juliaaano 17.05.2016 - 12:51
fonte

3 risposte

3

Come dice Brian (e il tuo riferimento ai documenti), Iterable s è molto più comune e a cosa sono abituati i programmatori. Quindi, usa Iterable - permette anche di usare l'istruzione "foreach", che non supporta Enumeration .

Dato che le collezioni non modificabili fanno parte del JDK di base, direi che i metodi di aggiunta / rimozione nella raccolta e i metodi di rimozione nell'iteratore sono esposti è proprio come è in Java. È piuttosto comune semplicemente documentare l'API sufficientemente e lanciare UnsupportedOperationException dove l'utente viola l'API.

Suggerirei l'implementazione di Tulains. Tuttavia, lancia un UnsupportedOperationException in remove invece di non fare nulla. Ciò comunica correttamente l'interfaccia: si restituisce una raccolta non modificabile. Questo è anche il comportamento delle classi JDK standard (ad esempio emptySet() e unmodifiableList() dalla classe Collections ).

Per completezza, l'implementazione (con un rappresentante sufficiente, avrei appena commentato la risposta di Tulains):

/* This is unmodifiable */
public class MyList<T> implements Iterable<T> {

    @Override
    public Iterator<T> iterator() {
        return new Iterator<T>() {
            @Override
            public boolean hasNext() {
                return false; // TODO: to implement
            }

            @Override
            public T next() {
                return null; // TODO: to implement
            }

            @Override
            public void remove() {  
                throw new UnsupportedOperationException();
            }
        };
    }

}

Nota che ho anche spostato Iterator in una classe interna per separare la raccolta e il suo iteratore. Questo è anche il modo in cui è fatto, ad esempio, per la classe Collections.UnmodifiableList .

    
risposta data 15.08.2016 - 16:19
fonte
2

Iterable<T> non ha un metodo remove() . Iterator<E> fa.

Se si restituisce un'enumerazione, il client deve ripetere l'iter in questo modo:

while(list.hasMoreElements()){
    e=nextElement();
}

Se vuoi che il codice client sia in grado di iterarlo in questo modo:

for(Element e; list){
    //do something with e
}

e tenerlo immutabile allo stesso tempo, dovresti estendere Iterator e Iterable , creare remove() lanciare IllegalStateException se chiamato, e restituire un oggetto di quel tipo:

public class MyList<T> implements Iterable<T>, Iterator<T> {

    @Override
    public Iterator<T> iterator() {
        return this;
    }

    @Override
    public boolean hasNext() {
        return false; // to implement
    }

    @Override
    public T next() {
        return null; // to implement
    }

    @Override
    public void remove() {  
      throw new IllegalStateException("I'm inmutable");
    }

    public static void main(String[] args) {
        MyList<String> l = new MyList<String>();
        for (String s: l){
            System.out.println(s);
        }
    }

}

È possibile restituire un oggetto di tipo MyList.

    
risposta data 15.08.2016 - 15:51
fonte
1

Normalmente mi aspetto un Iterable . È membro del framework Raccolte e come tale restituisce una Iterable ti consentirà di giocare bene con altri componenti.

Prendo il tuo punto di vista. immutabilità, però. Non c'è un modo particolarmente carino per restituire una raccolta di sola lettura. Potresti usare Collections.unmodifiableList() ma ciò non fornirà un controllo del tempo di compilazione. Lo stesso vale per la costruzione di una copia difensiva .

Restituire un Collection<? extends ElementType> se sei libero di restituire una raccolta anziché un iteratore, ti darà la sicurezza in fase di compilazione. Sono disponibili altre discussione qui

    
risposta data 17.05.2016 - 13:03
fonte

Leggi altre domande sui tag