L'ajout de deux Java 8 cours d'eau ou un élément supplémentaire à un flux
Je peux ajouter des ruisseaux ou des éléments supplémentaires, comme ceci:
Stream stream = Stream.concat(stream1, Stream.concat(stream2, Stream.of(element));
Et je peux ajouter de nouvelles choses que je vais, comme ceci:
Stream stream = Stream.concat(
Stream.concat(
stream1.filter(x -> x!=0), stream2)
.filter(x -> x!=1),
Stream.of(element))
.filter(x -> x!=2);
Mais c'est moche, parce que concat
est statique. Si concat
ont une méthode d'instance, les exemples ci-dessus serait beaucoup plus facile à lire:
Stream stream = stream1.concat(stream2).concat(element);
Et
Stream stream = stream1
.filter(x -> x!=0)
.concat(stream2)
.filter(x -> x!=1)
.concat(element)
.filter(x -> x!=2);
Ma question est:
1) Est-il une bonne raison pour laquelle concat
est statique? Ou est-il l'équivalent de la méthode d'instance je suis absent?
2) Dans tous les cas, est-il une meilleure manière de faire ceci?
- Il ressemble à chose qui n'étaient pas toujours comme ceci, mais je ne peux pas trouver la raison du pourquoi.
Vous devez vous connecter pour publier un commentaire.
Si vous ajoutez statique importations pour Flux.concat et Flux.de, le premier exemple peut être écrite comme suit:
Importation méthodes statiques avec des noms génériques peut résultat dans le code qui devient difficile à lire et à maintenir (espace de noms de la pollution). Donc, il peut être préférable de créer votre propre méthodes statiques avec des noms plus significatifs. Cependant, pour la démonstration, je vais en tenir à ce nom.
Avec ces deux méthodes statiques (éventuellement en combinaison avec d'statique des importations), les deux exemples peuvent être écrites comme suit:
Le code est maintenant beaucoup plus courte. Cependant, je suis d'accord que la lisibilité n'est pas améliorée. J'ai donc une autre solution.
Dans beaucoup de situations, Collectionneurs peut être utilisé pour étendre la fonctionnalité des cours d'eau. Avec les deux Collectionneurs au fond, les deux exemples peuvent être écrites comme suit:
La seule différence entre votre choix de la syntaxe et de la syntaxe ci-dessus est, que vous avez à remplacer concat(...) avec recueillir(concat(...)). Les deux méthodes statiques peuvent être mises en œuvre comme suit (en option utilisé en combinaison avec d'statique importations):
Bien sûr, il ya un inconvénient de cette solution qui mérite d'être mentionné. recueillir est une opération finale qui consomme tous les éléments du flux. En plus de cela, le collecteur concat crée un intermédiaire ArrayList chaque fois qu'il est utilisé dans la chaîne. Les deux opérations peuvent avoir un impact significatif sur le comportement de votre programme. Toutefois, si lisibilité est plus important que performance, il peut encore être très utile.
concat
collector bien lisible. Il semble étrange pour un ont un seul paramètre méthode statique nommée comme ceci, et aussi d'utilisercollect
pour la concaténation.It's a bad idea to import static methods with names
? Je suis vraiment intéressé - je trouve cela rend le code plus concis et lisible et beaucoup de gens à qui j'avais demandé à la pensée de même. Soins à donner quelques exemples pourquoi c'est généralement mauvais?compare(reverse(getType(42)), of(6 * 9).hashCode())
? Notez que je n'ai pas dit que statique importations est une mauvaise idée, mais statique importations pour les noms génériques commeof
etconcat
sont.Malheureusement, cette réponse est probablement que peu ou pas d'aide que ce soit, mais j'ai fait une analyse avancée de la Java Lambda liste de Diffusion afin de voir si je pouvais trouver la cause de cette conception. C'est ce que j'ai trouvé.
Au début il y avait une méthode d'une instance de Flux de données.concat(Stream)
Dans la liste de diffusion, je peux voir clairement la méthode a été implémentée à l'origine d'une méthode d'instance, comme vous pouvez le lire dans ce fil par Paul Sandoz, à propos de la méthode concat opération.
En elle, ils discutent des problèmes qui pourraient découler de ces cas dans lesquels le flux pourrait être infinie et que la concaténation signifierait dans ce cas, mais je ne pense pas que c'était la raison de la modification.
Vous voir dans cet autre fil que certains des premiers utilisateurs du JDK 8 interrogé sur le comportement de la méthode concat méthode d'instance lorsqu'il est utilisé avec des arguments nuls.
Ce autre thread révèle, cependant, que la conception de la méthode concat était en cours de discussion.
Refait les Ruisseaux.concat(Stream,Stream)
Mais sans aucune explication, tout à coup, les méthodes ont changé de méthodes statiques, comme vous pouvez le voir dans ce fil de discussion sur la manière de combiner les flux. C'est peut-être le seul thread messagerie qui jette un peu de lumière sur ce changement, mais il n'était pas assez clair pour moi, afin de déterminer la raison pour laquelle le refactoring. Mais nous pouvons voir qu'ils fait un commit dans lesquels ils ont suggéré de déplacer le
concat
méthode deStream
et dans la classe helperStreams
.Refait Flux.concat(Stream,Stream)
Plus tard, il a été déplacé de nouveau de
Streams
àStream
, mais encore une fois, aucune explication pour cela.Donc, ligne de fond, la raison de la conception n'est pas tout à fait clair pour moi et je ne pouvais pas trouver une bonne explication. Je pense que l'on peut encore poser la question dans la liste de diffusion.
Quelques solutions de rechange pour les Flux de Concaténation
Ce autre thread par Michael Hixson discute/demande sur les autres façons de combiner/concat flux
public static <T> Stream<T> concat(Stream<T>... streams) { return Stream.of(streams).reduce(Stream.empty(), Stream::concat);}
@SafeVarargs private static <T> Stream<T> concat(Stream<? extends T>... streams) { return Stream.of(streams).reduce(Stream.empty(),Stream::concat).map(Function.identity());}
Function.identity()
carte? Après tout, elle renvoie le même argument qu'elle reçoit. Cela ne devrait pas avoir d'effet dans le flux résultant. Ai-je raté quelque chose?return Stream.of(streams).reduce(Stream.empty(),Stream::concat)
retourne Flux<? s'étend T>.(Un truc<T> est sous-type de quelque Chose<? s'étend T>, pas dans l'autre sens, de sorte qu'il ne pouvait pas être exprimés) Supplémentaire.map(identity())
cast <? s'étend T> <T>. Il se fait grâce au mélange de java 8 cible 'types' de la méthode arguments et les types de retour et la signature de la méthode map (). En fait c'est la Fonction.<T> (identité).? extends T
, puisque vous pouvez utiliser capture de conversion. En tout cas, voici mon résumé extrait de code nous allons poursuivre la discussion dans les Gist.Mon StreamEx bibliothèque étend la fonctionnalité de Flux de l'API. En particulier, il propose des méthodes comme ajouter et ajouter qui résoudre ce problème (à l'interne qu'ils utilisent
concat
). Ces méthodes peuvent accepter un autre flux ou d'une collection ou varargs tableau. À l'aide de ma bibliothèque, votre problème peut être résolu de cette façon (à noter quex != 0
paraître étrange pour les non-primitif stream):Par la façon dont il est aussi un raccourci pour votre
filter
opération:Viens de faire:
où
identity()
est un statique à l'importation deFunction.identity()
.De la concaténation de plusieurs flux en un seul flux est le même que l'aplatissement d'un ruisseau.
Toutefois, malheureusement, pour une raison quelconque il n'y a pas de
flatten()
méthode surStream
, donc vous devez utiliserflatMap()
avec la fonction identité.Vous pouvez utiliser la Goyave est
Flux
.
concat(Flux<? s'étend T>... cours d'eau)
méthode, qui va être très court avec statique importations:Si vous n'avez pas l'esprit à l'aide de la 3e Partie des Bibliothèques cyclope-réagir a une extension de type de Flux de données qui vous permettra de le faire via l'ajout /préfixer les opérateurs.
Valeurs individuelles, des tableaux, des iterables, des Ruisseaux ou des réactifs-les ruisseaux, les Éditeurs peuvent être ajoutés et ajouté que les méthodes d'instance.
[Révélation je suis le développeur principal de cyclope-réagir]
À la fin de la journée, je ne suis pas intéressé dans la combinaison de cours d'eau, mais à obtenir le résultat combiné de traitement de chaque élément de tous ces flux.
Tout en combinant les flux pourrait s'avérer lourd (donc ce fil de discussion), en combinant leurs résultats du traitement est assez.
La clé pour résoudre les est de créer votre propre collecteur et de s'assurer que la fonction du fournisseur pour le nouveau collecteur renvoie la même collection à chaque fois (pas nouveau), le code ci-dessous illustre cette approche.
Comment sur l'écriture de votre propre méthode concat?
Ce, tout au moins, votre premier exemple beaucoup plus lisible.