L'altro giorno stavo giocando con un esperimento e avevo un ciclo for qualcosa del genere:
for (Node node : children) {
// do stuff with node ...
}
E poi l'ho cambiato per fare questo:
for (Node node : children.stream().filter(n -> n.isCreated())) {
// do stuff with node ...
}
E ottenuto questo errore: "Può solo scorrere su un array o un'istanza di java.lang.Iterable" Questo riapre alcune vecchie ferite per me. Ecco cosa trovo sciocco qui. Stream (la classe che non implementa Iterable) ha un metodo iterator (). Sono solo nel pensare che questa sia una grande svista? C'è qualche ragione logica per cui non dovrebbe essere dichiarato implementare Iterable? Ho capito che la programmazione funzionale è interessante e tutto ma non può essere che la ragione sia cercare di incoraggiare le persone a passare tutti i loro cicli da a% chiamate forEach()
.
Quindi la seconda parte di questo fastidio è che anche se fai questo:
for (Node node : children.stream().filter(n -> n.isCreated()).iterator()) {
// do stuff with node ...
}
Hai lo stesso identico errore. Questo è un vecchio fastidio per me perché quando hanno introdotto la sintassi for (:), non aveva mai avuto senso che Iterator non fosse una delle cose che potevi usare insieme a Iterable e array. Ora, sembra ancora più odioso dato che tutto ciò che dovrebbe essere fatto per rendere Iterator implementabile Iterable è aggiungere il seguente metodo a Iterator:
default Iterator<E> iterator() {
return this;
}
È abbastanza facile aggirare questi problemi con metodi come questo:
static <T> Iterable<T> iterable(final Stream<T> stream)
{
return new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return stream.iterator();
}
};
}
static <T> Iterable<T> iterable(final Iterator<T> iterator)
{
return new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return iterator;
}
};
}
Ma perché? Sembra sciocco doverlo fare. Qualcuno è a conoscenza del perché non è stato fatto o ha escogitato motivi legittimi per non rendere queste due interfacce Iterable?