Pourquoi ne Itérable<T> ne pas fournir de stream() et parallelStream() méthodes?
Je me demande pourquoi le Iterable
interface ne permet pas de fournir les stream()
et parallelStream()
méthodes. Considérons la classe suivante:
public class Hand implements Iterable<Card> {
private final List<Card> list = new ArrayList<>();
private final int capacity;
//...
@Override
public Iterator<Card> iterator() {
return list.iterator();
}
}
C'est une mise en œuvre d'un Main que vous pouvez avoir des cartes dans votre main tout en jouant à un Jeu de Cartes à collectionner.
Essentiellement, il enroule une List<Card>
, assure un maximum de capacité et offre d'autres fonctionnalités utiles. C'est mieux que de mettre en œuvre directement comme un List<Card>
.
Maintenant, pour convienience j'ai pensé qu'il serait bien de mettre en œuvre Iterable<Card>
, de sorte que vous pouvez utiliser renforcée pour boucles si vous souhaitez faire une boucle sur elle. (Mon Hand
de la classe fournit également un get(int index)
méthode, d'où le Iterable<Card>
est justifié à mon avis.)
La Iterable
interface fournit les suivantes (à gauche en sortant de javadoc):
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
Maintenant, pouvez-vous obtenir un flux avec:
Stream<Hand> stream = StreamSupport.stream(hand.spliterator(), false);
Donc sur la vraie question:
- Pourquoi ne
Iterable<T>
pas fournir une valeur par défaut des méthodes qui mettent en œuvre desstream()
etparallelStream()
, je ne vois rien qui pourrait la rendre impossible ou indésirable?
Une question connexe, j'ai trouvé est la suivante si: Pourquoi ne Stream<T> ne pas mettre en œuvre Itérable<T>?
Qui est curieusement il suggère de faire un peu l'inverse.
- Je suppose que c'est une bonne question, pour le Lambda Liste de Diffusion.
- Pourquoi est-il étrange de vouloir effectuer une itération sur un stream? Sinon, comment pourriez-vous éventuellement
break;
une itération? (Ok,Stream.findFirst()
pourrait être une solution, mais ça pourrait ne pas répondre à tous les besoins...) - Voir aussi Convertir en objet iterable de Flux à l'aide de Java JDK 8 pour la pratique de solutions de contournement.
Vous devez vous connecter pour publier un commentaire.
Ce n'était pas une omission; il y avait une discussion détaillée sur le EG liste au mois de juin 2013.
La discussion définitive du Groupe d'Experts est lié à ce fil.
Alors qu'il semblait "évident" (même pour le Groupe d'Experts, d'abord) que
stream()
semblait faire sens surIterable
, le fait queIterable
était si général est devenu un problème, parce que l'évidence de la signature:n'était pas toujours ce que vous allez vouloir. Certaines choses qui ont été
Iterable<Integer>
serait plutôt de leur flux de retour de méthode unIntStream
, par exemple. Mais de la misestream()
méthode de ce haut dans la hiérarchie de la rendrait impossible. Donc, au lieu de cela, nous avons fait c'est vraiment facile de faire uneStream
à partir d'unIterable
, en fournissant unspliterator()
méthode. La mise en œuvre destream()
dansCollection
est juste:Tout client peut obtenir le flux qu'ils veulent à partir d'un
Iterable
avec:À la fin, nous avons conclu que l'ajout de
stream()
àIterable
serait une erreur.Iterable<Integer>
(je pense que vous êtes en train de parler?) souhaitez retourner unIntStream
. Serait l'objet iterable alors pas plutôt unPrimitiveIterator.OfInt
? Ou avez-vous peut-être dire un autre cas d'utilisation?Iterable
ontstream()
, puis les développeurs peuvent ajouterintStream()
le cas échéant? Aussi, je soupçonne le cas où le problème que vous décrivez serait de se produire sont rares.Stream.of(Iterable)
, ce qui permettrait au moins de faire de la méthode raisonnablement identifiable par la lecture de la documentation de l'API -- comme de quelqu'un qui n'a jamais vraiment travaillé avec le fonctionnement interne de Flux, je n'avais même jamais regardé àStreamSupport
, qui est décrit dans la documentation comme les opérations de bas niveau", qui sont "principalement pour la bibliothèque des écrivains".spliterator
-- sérieusement, qu'est ce que ça s'appelle? Sonne comme une 3ème partie de la bibliothèque JS pour moi!java.util.stream
etjava.util.function
ont un traitement spécial pour les primitives? Nous avonsIntStream
etIntUnaryOperator
etc. mais pasIntList
ouIntIterable
etc. Alors il n'y aurait pas le problème deIterable<Integer>
vouloirIntStream
type de retour.J'ai fait une enquête dans plusieurs de le projet lambda listes de diffusion, et je crois que j'ai trouvé quelques discussions intéressantes.
Je n'ai pas trouvé d'explication satisfaisante à ce jour. Après la lecture de tout cela, je conclus que c'était juste une omission. Mais vous pouvez voir ici qu'il a été évoqué à plusieurs reprises au fil des ans lors de la conception de l'API.
Lambda Libs Spec Experts
J'ai trouvé une discussion à ce sujet dans le Lambda Libs Spec Experts de la liste de diffusion:
Sous Itérable/Itérateur.stream() Sam Pullara dit:
Et puis Brian Goetz a répondu:
Et plus tard
De Délibérations antérieures Lambda Liste de Diffusion
Cela peut ne pas être la réponse que vous cherchez, mais dans le Projet Lambda liste de diffusion cela a été brièvement abordée. Peut-être ce qui contribue à favoriser une discussion plus large sur le sujet.
Dans les paroles de Brian Goetz sous Les flux de Itérable:
Contradiction?
Bien, il semble que la discussion est basée sur les modifications que le Groupe d'Experts n', la conception initiale de cours d'eau qui a d'abord été fondée sur les itérateurs.
Même ainsi, il est intéressant de remarquer que, dans une interface comme la Collecte, le flux de la méthode est définie comme:
Qui pourrait être exactement le même code utilisé dans l'Itérable interface.
Donc, c'est pourquoi j'ai dit que cette réponse n'est probablement pas satisfaisante, mais tout de même intéressants pour la discussion.
Preuve de Refactoring
Continue avec l'analyse de la liste de diffusion, il semble que la splitIterator méthode a été à l'origine dans la Collection de l'interface, et à un certain moment en 2013, ils se sont déplacés jusqu'à Itératif.
Pull splitIterator en place de la Collecte à l'Itérable.
Conclusion/Théories?
Alors les chances sont que le manque de méthode dans l'objet iterable est juste une omission, car on dirait qu'ils devraient avoir déplacé le flux de la méthode ainsi quand ils ont déménagé de la splitIterator en place de la Collecte à l'Itératif.
Si il y a d'autres raisons de ceux qui ne sont pas évidents. Quelqu'un d'autre a d'autres théories?
spliterator()
de laIterable
, alors tous les problèmes sont résolus, et vous pouvez trivialement mettre en œuvrestream()
etparallelStream()
..Si vous connaissez la taille que vous pourriez utiliser
java.util.Collection
qui fournit lestream()
méthode:Et puis:
J'ai connu le même problème et a été surpris de voir que mon
Iterable
mise en œuvre pourrait très facilement être étendu à unAbstractCollection
mise en œuvre en ajoutant simplement lesize()
méthode (heureusement, j'avais la taille de la collection 🙂Vous devriez également envisager de remplacer
Spliterator<E> spliterator()
.