J'ai fait une enquête dans plusieurs des listes de diffusion du projet lambda et je pense avoir trouvé quelques discussions intéressantes.
Je n'ai jusqu'à présent pas trouvé d'explication satisfaisante. Après avoir lu tout cela, j'ai conclu que c'était juste une omission. Mais vous pouvez voir ici qu'il a été discuté plusieurs fois au cours des années lors de la conception de l'API.
Experts en spécifications Lambda Libs
J'ai trouvé une discussion à ce sujet dans la liste de diffusion Lambda Libs Spec Experts :
Sous Iterable / Iterator.stream (), Sam Pullara a déclaré:
Je travaillais avec Brian pour voir comment la fonctionnalité de limite / sous-flux [1] pourrait être implémentée et il a suggéré que la conversion vers Iterator était la bonne façon de procéder. J'avais pensé à cette solution mais je n'ai trouvé aucun moyen évident de prendre un itérateur et de le transformer en un flux. Il s'avère qu'il est là, il vous suffit de convertir d'abord l'itérateur en séparateur, puis de convertir le séparateur en flux. Cela m'amène donc à revenir sur la question de savoir si nous devrions les suspendre directement à Iterable / Iterator ou aux deux.
Ma suggestion est de l'avoir au moins sur Iterator afin que vous puissiez vous déplacer proprement entre les deux mondes et il serait également facilement détectable plutôt que d'avoir à le faire:
Streams.stream (Spliterators.spliteratorUnknownSize (itérateur, Spliterator.ORDERED))
Et puis Brian Goetz a répondu :
Je pense que le point de Sam était qu'il existe de nombreuses classes de bibliothèque qui vous donnent un itérateur mais ne vous permettent pas nécessairement d'écrire votre propre séparateur. Donc, tout ce que vous pouvez faire est d'appeler le flux (spliteratorUnknownSize (itérateur)). Sam suggère que nous définissions Iterator.stream () pour le faire pour vous.
Je voudrais conserver les méthodes stream () et spliterator () comme étant destinées aux rédacteurs de bibliothèque / utilisateurs avancés.
Et ensuite
"Étant donné qu'écrire un Spliterator est plus facile que d'écrire un Iterator, je préférerais simplement écrire un Spliterator au lieu d'un Iterator (Iterator a tellement 90 ans :)"
Vous manquez le point, cependant. Il y a des millions de classes qui vous offrent déjà un itérateur. Et beaucoup d'entre eux ne sont pas prêts pour le séparateur.
Discussions précédentes dans la liste de diffusion Lambda
Ce n'est peut-être pas la réponse que vous recherchez, mais dans la liste de diffusion Project Lambda cela a été brièvement discuté. Cela peut peut-être favoriser une discussion plus large sur le sujet.
Pour reprendre les mots de Brian Goetz sous Streams from Iterable :
Reculer...
Il existe de nombreuses façons de créer un flux. Plus vous avez d'informations sur la description des éléments, plus la bibliothèque de flux peut vous offrir de fonctionnalités et de performances. Dans l'ordre du moins à la plupart des informations, ils sont:
Itérateur
Itérateur + taille
Spliterator
Spliterator qui connaît sa taille
Séparateur qui connaît sa taille et sait en outre que toutes les sous-divisions connaissent leur taille.
(Certains peuvent être surpris de constater que nous pouvons extraire le parallélisme même à partir d'un itérateur muet dans les cas où Q (travail par élément) n'est pas trivial.)
Si Iterable avait une méthode stream (), il envelopperait simplement un Iterator avec un Spliterator, sans aucune information de taille. Mais, la plupart des choses qui sont Iterable faire des informations de taille. Ce qui signifie que nous servons des flux déficients. Ce n'est pas si bon.
Un inconvénient de la pratique de l'API décrite par Stephen ici, d'accepter Iterable au lieu de Collection, est que vous forcez les choses à travers un "petit tuyau" et que vous jetez donc les informations de taille lorsqu'elles pourraient être utiles. C'est bien si tout ce que vous faites est pour chacun d'eux, mais si vous voulez en faire plus, c'est mieux si vous pouvez conserver toutes les informations que vous voulez.
La valeur par défaut fournie par Iterable serait vraiment minable - elle éliminerait la taille même si la grande majorité des Iterables connaissent cette information.
Contradiction?
Cependant, il semble que la discussion soit basée sur les changements que le Groupe d'experts a apportés à la conception initiale des Streams qui était initialement basée sur des itérateurs.
Même ainsi, il est intéressant de noter que dans une interface comme Collection, la méthode stream est définie comme:
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
Ce qui pourrait être exactement le même code utilisé dans l'interface Iterable.
C'est pourquoi j'ai dit que cette réponse n'est probablement pas satisfaisante, mais toujours intéressante pour la discussion.
Preuve de refactorisation
Poursuivant l'analyse dans la liste de diffusion, il semble que la méthode splitIterator était à l'origine dans l'interface Collection, et à un moment donné en 2013, ils l'ont déplacée vers Iterable.
Tirez splitIterator de Collection à Iterable .
Conclusion / Théories?
Ensuite, il est probable que l'absence de la méthode dans Iterable ne soit qu'une omission, car il semble qu'ils auraient également dû déplacer la méthode de flux lorsqu'ils ont déplacé le splitIterator de Collection à Iterable.
S'il y a d'autres raisons, celles-ci ne sont pas évidentes. Quelqu'un d'autre a d'autres théories?