En Java 8, nous avons la classe Stream <T> , qui a curieusement une méthode
Iterator<T> iterator()
Vous vous attendez donc à ce qu'il implémente l'interface Iterable <T> , qui nécessite exactement cette méthode, mais ce n'est pas le cas.
Quand je veux parcourir un Stream en utilisant une boucle foreach, je dois faire quelque chose comme
public static Iterable<T> getIterable(Stream<T> s) {
return new Iterable<T> {
@Override
public Iterator<T> iterator() {
return s.iterator();
}
};
}
for (T element : getIterable(s)) { ... }
Est-ce que j'ai râté quelque chose?
java
java-8
java-stream
iterable
gronder
la source
la source
Stream
aux API héritées quiIterable
getIterable()
return s::iterator;
for (T element : stream::iterator)
, donc je préférerais toujours que Stream implémente égalementIterable
une méthodetoIterable()
.Réponses:
Les gens ont déjà demandé la même chose sur la liste de diffusion ☺. La principale raison est qu'Iterable a également une sémantique réitérable, contrairement à Stream.
la source
Iterable
sur la question de savoir si elleiterator
devrait toujours ou non être appelable plusieurs fois. C'est quelque chose qu'ils devraient y mettre. Cela semble être plus une pratique standard qu'une spécification formelle.Pour convertir un
Stream
en unIterable
, vous pouvez fairePour passer un
Stream
à une méthode qui attendIterable
,simplement
mais cela a probablement l'air drôle; il vaudrait peut-être mieux être un peu plus explicite
la source
for(X x : (Iterable<X>)stream::iterator)
, même si cela semble laid. Vraiment, toute la situation est tout simplement absurde.IntStream.range(0,N).forEach(System.out::println)
stream::iterator
etstream.iterator()
, qui rend le premier acceptable pour un,Iterable
mais pas le second?Iterable
est une interface fonctionnelle, donc passer une fonction qui l'implémente est suffisant.Je tiens à souligner que
StreamEx
cela met en œuvreIterable
(etStream
), ainsi qu'une foule d'autres fonctionnalités extrêmement impressionnantes manquantesStream
.la source
Vous pouvez utiliser un Stream dans une
for
boucle comme suit:(Exécutez cet extrait ici )
(Cela utilise une distribution d'interface fonctionnelle Java 8.)
(Ceci est couvert dans certains des commentaires ci-dessus (par exemple Aleksandr Dubinsky ), mais je voulais le retirer dans une réponse pour le rendre plus visible.)
la source
kennytm a expliqué pourquoi il n'est pas sûr de traiter un
Stream
comme unIterable
, et Zhong Yu a proposé une solution de contournement qui permet d'utiliser unStream
comme dansIterable
, bien que de manière dangereuse. Il est possible d'obtenir le meilleur des deux mondes: un réutilisable àIterable
partir d'unStream
qui répond à toutes les garanties apportées par leIterable
cahier des charges.Remarque:
SomeType
n'est pas un paramètre de type ici - vous devez le remplacer par un type approprié (par exemple,String
) ou recourir à la réflexionIl y a un inconvénient majeur:
Les avantages de l'itération paresseuse seront perdus. Si vous envisagez d'itérer immédiatement toutes les valeurs du thread actuel, les frais généraux seront négligeables. Cependant, si vous prévoyez d'itérer seulement partiellement ou dans un thread différent, cette itération immédiate et complète pourrait avoir des conséquences inattendues.
Le grand avantage, bien sûr, est que vous pouvez réutiliser le
Iterable
, alors(Iterable<SomeType>) stream::iterator
qu'il ne permettrait qu'une seule utilisation. Si le code de réception itère plusieurs fois sur la collection, cela est non seulement nécessaire, mais probablement bénéfique pour les performances.la source
Stream.toArray()
renvoie un tableau, pas unIterable
, donc ce code ne compile toujours pas. mais cela peut être un bogue dans l'éclipse, car IntelliJ semble le compilerStream
ne met pas en œuvreIterable
. La compréhension générale deIterable
tout ce qui peut être répété, souvent encore et encore.Stream
peut ne pas être rejouable.La seule solution de contournement à laquelle je peux penser, où un itérable basé sur un flux est également rejouable, est de recréer le flux. J'utilise un
Supplier
ci - dessous pour créer une nouvelle instance de flux, chaque fois qu'un nouvel itérateur est créé.la source
Si cela ne vous dérange pas d'utiliser des bibliothèques tierces, cyclops-react définit un Stream qui implémente à la fois Stream et Iterable et est également rejouable (résolution du problème décrit par Kennedy ).
ou :-
[Divulgation Je suis le développeur principal de cyclops-react]
la source
Pas parfait, mais fonctionnera:
Pas parfait car il récupérera tous les éléments du flux et les placera dans ce
List
qui n'est pas exactement de quoiIterable
ilStream
s'agit. Ils sont censés être paresseux .la source
Vous pouvez parcourir tous les fichiers d'un dossier en utilisant
Stream<Path>
comme ceci:la source