Ho fatto un'indagine in diverse mailing list del progetto lambda e penso di aver trovato alcune discussioni interessanti.
Finora non ho trovato una spiegazione soddisfacente. Dopo aver letto tutto ciò, ho concluso che era solo un'omissione. Ma puoi vedere qui che è stato discusso più volte nel corso degli anni durante la progettazione dell'API.
Esperti di specifiche di Lambda Libs
Ho trovato una discussione al riguardo nella mailing list degli esperti di Lambda Libs :
Sotto Iterable / Iterator.stream () Sam Pullara ha detto:
Stavo lavorando con Brian per vedere come implementare la funzionalità limit / substream [1] e mi ha suggerito che la conversione in Iterator fosse il modo giusto per farlo. Avevo pensato a quella soluzione ma non ho trovato alcun modo ovvio per prendere un iteratore e trasformarlo in un flusso. Si scopre che è lì dentro, devi solo convertire l'iteratore in uno spliterator e quindi convertire lo spliterator in uno stream. Quindi questo mi porta a rivisitare se dovremmo avere questi sospesi direttamente da Iterable / Iterator o entrambi.
Il mio suggerimento è di averlo almeno su Iterator in modo da poter spostarti in modo pulito tra i due mondi e sarebbe anche facilmente individuabile piuttosto che doverlo fare:
Streams.stream (Spliterators.spliteratorUnknownSize (iterator, Spliterator.ORDERED))
E poi Brian Goetz ha risposto :
Penso che il punto di Sam fosse che ci sono molte classi di biblioteche che ti danno un Iteratore ma non ti lasciano necessariamente scrivere il tuo proprio divisore. Quindi tutto ciò che puoi fare è chiamare il flusso (spliteratorUnknownSize (iteratore)). Sam sta suggerendo di definire Iterator.stream () per farlo per te.
Vorrei mantenere i metodi stream () e spliterator () come per gli scrittori di librerie / utenti avanzati.
E più tardi
"Dato che scrivere uno Spliterator è più facile che scrivere uno Iterator, preferirei semplicemente scrivere uno Spliterator invece di uno Iterator (Iterator è così anni '90 :)"
Ti manca il punto, però. Ci sono miliardi di classi là fuori che ti danno già un Iteratore. E molti di loro non sono pronti per lo splitterator.
Discussioni precedenti in Lambda Mailing List
Questa potrebbe non essere la risposta che stai cercando, ma nella mailing list di Project Lambda questa è stata brevemente discussa. Forse questo aiuta a favorire una discussione più ampia sull'argomento.
Nelle parole di Brian Goetz sotto Streams from Iterable :
Arretrare...
Esistono molti modi per creare uno stream. Più informazioni hai su come descrivere gli elementi, maggiore è la funzionalità e le prestazioni che la libreria di flussi può darti. Per almeno la maggior parte delle informazioni, sono:
Iterator
Iteratore + dimensione
Spliterator
Spliterator che conosce le sue dimensioni
Spliterator che conosce le sue dimensioni e inoltre sa che tutte le suddivisioni secondarie conoscono le loro dimensioni.
(Alcuni potrebbero essere sorpresi di scoprire che possiamo estrarre il parallelismo anche da un muto iteratore nei casi in cui Q (lavoro per elemento) non è banale.)
Se Iterable avesse un metodo stream (), avvolgerebbe semplicemente un Iterator con un Spliterator, senza informazioni sulle dimensioni. Ma, la maggior parte delle cose che sono Iterable fare avere informazioni sulle dimensioni. Ciò significa che stiamo offrendo flussi carenti. Non va molto bene.
Un aspetto negativo della pratica API delineata da Stephen qui, di accettare Iterable invece di Collection, è che stai forzando le cose attraverso una "piccola pipe" e quindi scartando le informazioni sulle dimensioni quando potrebbero essere utili. Va bene se tutto ciò che stai facendo è per ogni cosa, ma se vuoi fare di più, è meglio se puoi conservare tutte le informazioni che desideri.
L'impostazione predefinita fornita da Iterable sarebbe davvero scadente - eliminerebbe le dimensioni anche se la stragrande maggioranza degli Iterable conosce tali informazioni.
Contraddizione?
Tuttavia, sembra che la discussione si basi sui cambiamenti che il gruppo di esperti ha apportato alla progettazione iniziale di Stream, inizialmente basata su iteratori.
Tuttavia, è interessante notare che in un'interfaccia come Collection, il metodo stream è definito come:
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
Quale potrebbe essere esattamente lo stesso codice utilizzato nell'interfaccia Iterable.
Quindi, ecco perché ho detto che questa risposta non è probabilmente soddisfacente, ma comunque interessante per la discussione.
Prova di refactoring
Continuando con l'analisi nella mailing list, sembra che il metodo splitIterator fosse originariamente nell'interfaccia Collection, e ad un certo punto nel 2013 lo hanno spostato su Iterable.
Tirare splitIterator in su da Collection a Iterable .
Conclusione / Theories?
Quindi è probabile che la mancanza del metodo in Iterable sia solo un'omissione, poiché sembra che avrebbero dovuto spostare anche il metodo stream quando hanno spostato splitIterator da Collection a Iterable.
Se ci sono altri motivi, questi non sono evidenti. Qualcun altro ha altre teorie?