Transcription
1. Introduction: Bonjour à tous,
bienvenue dans la classe Java eight streams, une introduction
pratique. Je m'appelle Journeyman, et dans ce cours, je
vais vous expliquer tout sur les streams
et leur utilisation. Ce cours est destiné à doser, ayant peu ou pas d'
expérience avec les ruisseaux est de la gaze pour vous donner un
aperçu de la possibilité des ruisseaux. Vous reconnaissez les situations dans
lesquelles les flux peuvent être utiles. Nous allons approfondir l'utilisation
des streams et en général. Vous souhaitez les utiliser dans interfaces
fonctionnelles
et des lambdas. Je vais expliquer les opérations couramment
utilisées pour ceux qui ont envie d'une approche
plus pratique. Ce cours
propose également des exercices pour mettre en pratique les connaissances
apprises. Allons-y.
2. Cas d'utilisation et d'utilisation du flux: Utilisation et cas d'utilisation des flux. Les cours
d'eau utilisent simplement un cours d'eau pour
traiter une collection d'objets. Dans un chapitre ultérieur, nous examinerons plus en détail certaines méthodes spécifiques de traitement d'une collection. Mais pour l'instant, considérez simplement
le traitement comme le filtrage, la
modification et
l'enrichissement des données à collecter. Notez toutefois que les
productions utilisées comme entrées pour les flux ne sont pas
réellement modifiées par les flux. Au lieu de cela, l'exécution
d'un flux nous donne résultats
distincts déconnectés de la collection d'origine. Ces étapes
de traitement des opérations sont écrites de manière fonctionnellement
descriptive. Cela signifie qu'un stream se lit comme
une histoire lorsqu'il est fait correctement, ce
qui le
rend incroyablement utile. Pour mettre cela en valeur. Voici un exemple de méthode
classique de filtrage, de
collecte, de tri
et d'impression de certaines données. J'utilise la même logique
écrite dans les streams. Je suis sûr que vous serez capable comprendre les deux
côtés un jour, mais je pense que nous sommes tous d'accord pour dire que l'utilisation de streams permet l'utilisation de streams permet de comprendre
beaucoup plus facilement
ce que fait le code. Alors, vous l'avez.
Les flux sont utilisés pour traiter une collection d'articles
de manière très raisonnable. Comment fonctionnent les streams ? Comme je viens de le dire, les streams fonctionnent
sur une collection d'objets. Vous vous êtes peut-être rendu compte que la collection de mots
correspond à une interface. En Java. L'interface trouvée dans
le package Java util est notre lien pour travailler avec
les flux. La plupart du temps, vous utilisez généralement une
liste ou un ensemble pour démarrer un flux qui étend l'interface
de collecte. Il existe d'autres moyens
de créer un flux. Nous ne
les aborderons pas dans ce cours. Vous pouvez les trouver
dans les ressources. Avec l'arrivée de Java Eight, une méthode par défaut appelée stream a été ajoutée à
l'interface de collecte. Pour ceux qui ne connaissent pas
les méthodes par défaut. Les méthodes par défaut vous
permettent d'ajouter nouvelles fonctionnalités
aux interfaces de vos bibliothèques et de garantir la compatibilité
binaire avec le code écrit pour les anciennes
versions des interfaces. Ce flux de méthode par défaut renvoie une instance
du flux coûte à la classe d'API centrale qui nous permet de
travailler avec eux. Après avoir créé le flux, vous pouvez désormais enchaîner
les opérations et exécuter le flux. Nous en reparlerons plus tard. Résumons ce que
nous avons appris jusqu'à présent. Les flux sont utilisés pour traiter une collection d'éléments de
manière très lisible. Les flux ne modifient pas
cette collection source, mais créent
un résultat distinct déconnecté de la collection
d'origine. L'interface de flux est le coût central de l'API lié à
l'utilisation des flux. Tout ce qui étend
ou
implémente l'interface de collecte possède une méthode de flux par défaut pour interagir avec la classe d'API
centrale des ensembles.
3. Interfaces fonctionnelles et Lambda: Interfaces fonctionnelles
et lambdas. Avant de commencer à
parler des opérations de streaming, nous devons
parler des conditions préalables l'utilisation
de strips. Les Lambdas. Les lambdas sont essentiellement des classes
internes anonymes, des interfaces
fonctionnelles dont le compilateur Java
indique implicitement les informations nécessaires. Commençons par le début. Classes internes anonymes. Lorsque vous implémentez une interface, vous allez implémenter
toutes ses méthodes. Voici un exemple
où vous créez classe
implémentée
et l'instanciez. Nous avons ici une interface appelée mon interface
avec l'impression. Une méthode importante est implémentée par mon interface. Mais que se passe-t-il si j'ai besoin d'une implémentation légèrement
différente des impressions, une méthode
importante. Dans ce scénario, je
devrais créer une autre classe qui
implémente mon interface. Encore une fois. Imaginez que si vous avez
dix variances différentes, elles seront bientôt
encombrées. C'est un signal pour les classes internes
anonymes. La classe interne anonyme est
une extension d'une classe. Une implémentation
d'une interface sans nom, donc anonyme. Nous allons nous concentrer sur la partie S de l'
interface. C'est la partie la plus importante
dans le contexte des streams. Comme ils n'ont pas de nom, nous ne pouvons pas créer d'instance de la
classe interne anonyme à elle seule. Au lieu de cela, vous devez déclarer et instancier la classe interne
anonyme dans une seule expression. Cette expression
se présente comme suit, ce qui
se traduit par ce qui suit. Lors de la création de la version anonyme de classe
interne de mes informations d'interface. Comme vous pouvez le constater, nous avons
créé une instance de mon interface sans avoir besoin d' une classe implémentant
l'interface. Et si je souhaite ajouter une nouvelle implémentation de mon interface, je peux simplement le faire.
Voilà, nous l'avons. Les classes internes anonymes
peuvent être utilisées pour implémenter une interface sans avoir
à définir une classe rigide. Vous pouvez simplement
les créer à la volée. Interfaces fonctionnelles. L'interface fonctionnelle n'
est qu'une interface , sauf qu'elle ne contient qu' une seule méthode qui
doit être mise en œuvre. Toute interface répondant à ces critères est une interface
fonctionnelle. Tout comme notre
exemple d'interface tout à l'heure. Bien que cela ne soit pas nécessaire, vous pouvez ajouter l'
annotation de l'interface fonctionnelle pour montrer votre intention. En prime, le compilateur lancera une exception lors de la compilation
lorsqu'il ne s'agit pas réellement d'une interface fonctionnelle lors de l'utilisation de cette annotation. Passons en revue les interfaces fonctionnelles les plus
couramment utilisées lors de l'utilisation de flux. premier est le
fournisseur qui a admis les gets. Il ne s'attend à aucun argument, mais renvoie quelque chose. Le fournisseur
vous fournit quelque chose, généralement un objet neuf,
vide et propre. On pourrait le voir comme une usine. Le suivant est le
prédicat. Avec admis. Elle attend un argument, l'évalue et
renvoie une valeur booléenne. Comme son nom l'indique, il s'agit essentiellement d'un test. L'argument t répond-il aux critères
donnés par oui ou par non ? consommateur avec ses
méthodes accepte, accepte un argument, en
fait quelque chose, mais ne renvoie rien, consommant
littéralement les
arguments au cours du processus. Le consommateur de vélo fait
la même chose que le consommateur, sauf qu'il s'attend à deux arguments. La fonction et ses méthodes s'appliquent. Il s'attend à une dispute, il en
fait quelque chose. Et les retours en arguments mappent ou enrichissent
essentiellement l'argument dans le processus, les arguments r et t
peuvent être de la même classe. La fonction by fait
la même chose que la fonction. Excepted attend deux arguments, T et U en font
quelque chose. Les retours sont exactement
comme la fonction. Les arguments peuvent être de la
même classe si nécessaire. Et sur cette note, nous arrivons à la dernière interface
fonctionnelle commune. Opérateur binaire. L'opérateur binaire est une extension
de la fonction by où T, U et R sont
exactement la même classe. Assurez-vous d'avoir une
bonne compréhension des interfaces fonctionnelles en général et de ces interfaces
courantes avant de continuer. Cela vous aidera à comprendre plus facilement les
opérations
lambdas et les flux de données. Expressions lambda. Les classes internes
anonymes d' interfaces
fonctionnelles dont le compilateur Java
connaît implicitement les informations nécessaires sont les plus regroupées. Nous savons maintenant ce qu'
est une classe interne
anonyme et comment nous devons encore implémenter toutes les méthodes
d'une interface. Nous remarquons que
les interfaces fonctionnelles sont des interfaces normales, sauf qu'elles n'ont qu'
une seule
méthode à implémenter. Comme une interface fonctionnelle
ne possède qu'une seule méthode, le compilateur est
capable de comprendre de nombreuses informations en
fonction du contexte. En tant que développeur, vous pouvez
omettre ces informations. Cela permet au compilateur de savoir que
vous omettez des choses. Problèmes de syntaxe Lambda. Nous allons commencer par une classe interne
anonyme irrégulière et convertir en une expression
lambda complète ,
pièce par pièce. Ou utilisez le prédicat
d'interface fonctionnelle pour tester si un entier donné
est supérieur à un. En surveillant le signe égal, nous avons remarqué le nom de l'
interface que nous implémentons. Le corps de la classe interne
anonyme, la signature de la méthode et le corps des méthodes que
nous implémentons. Regardez de plus près le nom de
l'interface et la signature de la méthode. Voyez-vous comment le compilateur
pourrait déduire ces connaissances ? Remarquez que les
noms d'interface se trouvent déjà sur le côté gauche
des instructions Equal. Remarquez que puisque le prédicat
est une interface fonctionnelle, il n'y a qu'une seule
méthode à implémenter. Nous savons donc déjà quelles
méthodes nous mettons en œuvre. Ces deux types d' informations peuvent être
déduits par le compilateur. Notre première étape consiste à écrire ceci en utilisant la
syntaxe groupée, la flèche. Avec elle. Nous allons supprimer le nom de l'
interface, le nom de la méthode. Cela a déjà l'air
beaucoup plus propre, non ? Nous voyons ici l'entrée
des méthodes, l'entier sur le
côté gauche de la flèche et le corps de la
méthode sur le côté droit. Mais il y a encore
des informations que nous pouvons omettre dans ce cas. Comme il existe une méthode
unique et le compilateur connaît
sa signature,
le compilateur peut déduire le type
d'entrée à partir du contexte. Les crochets autour des entrées
ont également disparu. Cela n'est possible que parce qu'
il s'agit d'un seul paramètre. Si vous en avez deux ou plus, les crochets sont obligatoires. Il y a encore une chose que
nous pouvons maintenant déduire. Cela a trait au corps
et à la déclaration de retour. Dans le cas d' une seule ligne de code dans
le corps de la méthode, le compilateur peut en déduire
que cette ligne de code est en fait l'
instruction de retour du corps. Avec cette dernière étape, nous avons atteint l'expression
lambda complète. Vous verrez tout le temps
lorsque vous travaillez avec des chaînes. En fait, il existe un moyen d'
écrire le lambda encore plus court. Dans certains cas. C'est ce qu'on appelle la référence de méthode Mais je suggère de le rechercher
vous-même lorsque vous aurez une bonne compréhension des
longues doses en général. Une dernière chose importante à
mentionner à propos de lumped us est que les variables
locales qui y sont utilisées doivent être finales ou
effectivement finales. fait, final
signifie une variable qui ne possède pas
le mot clé final, mais dont la valeur ne change pas
après sa première attribution. La raison en est que nous sommes
regroupés en gros un morceau de code que vous pouvez
exécuter avec d'autres méthodes. Comme la façon dont vous pouvez
transmettre notre prédicat à une opération de filtre
au sein d'une chaîne. Pour cette raison,
Java doit créer une copie de la variable locale
à utiliser dans les poumons. Pour éviter les problèmes de simultanéité. L'alpha a décidé de restreindre complètement
les variables locales. Résumons ce que
nous avons appris jusqu'à présent. Les classes internes anonymes sont des classes internes qui implémentent une interface
sans nom, et qui doivent être déclarées
et instanciées une seule fois. Les interfaces fonctionnelles sont des interfaces régulières , sauf que les seules contiennent une seule méthode qui
doit être mise en œuvre. L'annotation de
l'interface fonctionnelle qui
peut être utilisée pour appliquer
cette règle n'est pas nécessaire. Nous sommes regroupés en classes
internes anonymes d'
interfaces fonctionnelles dont le compilateur Java peut déduire informations
manquantes
en fonction du contexte. Nous savons maintenant comment créer une expression lambda et une classe interne anonyme
irrégulière. Enfin, les variables locales utilisées dans lumped us doivent être
finales ou effectivement correctes.
4. Opérations de diffusion: Dans les chapitres suivants, j'expliquerai les
opérations couramment utilisées sur les chaînes. Mais d'abord, nous devons parler des deux types d'opérations
possibles, les opérations intermédiaires et les opérations
terminales. Un flux n'est complètement exécuté que lorsqu'une
opération sur un terminal est utilisée. Par conséquent, un flux se termine
toujours par une opération de terminal et ne peut avoir qu'un seul d'
entre eux dans un flux. Les opérations intermédiaires sont toutes les opérations effectuées avant l'opération finale du
terminal. Les opérations intermédiaires
renvoient une instance de flux, ce qui permet de les
enchaîner toutes. Comme toutes les
opérations intermédiaires renvoient un flux, vous pouvez stocker une chaîne sans opérations de
terminal
dans une variable. Merci aujourd'hui, vous pouvez donc
ajouter des étapes à votre flux en fonction d'influences
externes, comme un filtre différent ou une manière différente d'
enrichir les données. Attention,
même si vous pouvez stocker des
opérations intermédiaires dans des variables, il n'est pas possible d'exécuter le même flux deux fois avec
une opération sur un terminal. Le compilateur ne le
reconnaît pas, mais vous obtiendrez une exception
comme celle-ci lors de l'exécution. Encore une fois. Les opérations intermédiaires
renvoient un flux et peuvent donc être liées
et stockées dans des variables. Les opérations intermédiaires seules
n'exécutent pas un flux. Une opération de terminal exécute le flux complet et renvoie
une valeur autre qu'un flux. Un flux ne peut être
exécuté qu'une seule fois avec une opération sur un
terminal. vous essayez de le faire deux fois , une exception se produit
lors de l'exécution. Forts de ces connaissances,
nous passerons
aux opérations couramment utilisées.
5. Exploitation intermédiaire : filtre: Commençons par les bases. Filtre. Le filtre est une
opération intermédiaire qui permet filtrer les objets des chaînes qui ne
passent pas le test donné. Vous pouvez voir le filtre d'opération
intermédiaire comme l'équivalent en flux
d'une instruction if. entrée est un prédicat qui, comme nous l'avons appris,
reçoit un objet, effectue un test dessus, renvoie vrai ou faux selon qu'il
a réussi le test ou non. Voici un exemple de son utilisation. Et ne vous inquiétez pas
pour les autres opérations. Nous y reviendrons bientôt. Dans cet exemple, nous
utilisons un filtre pour continuer le flux uniquement avec les objets dont la liste de
numéros de téléphone est vide. Avant de revenir aux
clients restants sous forme de liste, filtrage peut être effectué en utilisant
n'importe quelle valeur finale efficace. Ici, nous filtrons en
fonction de notre variable locale, par exemple, nous pouvons également les
enchaîner en utilisant plusieurs
filtres d'affilée. L'opération de filtrage est un excellent exemple de la manière dont les flux rendent votre
code plus lisible. Surtout si vous avez stocké
longtemps dans une valeur comme celle-ci. Vous pouvez désormais voir en un coup d'œil ce que nous
filtrons.
6. Exploitation du terminal : pour chaque: Notre première
opération de terminal pour chacun d'entre eux. Le ForEach est une opération de terminal très
simple. Il est utilisé pour effectuer une certaine action sur tous les
éléments du flux. En supposant que les éléments
du processus, ses intrants, sont des consommateurs. Il prend donc un objet, en
fait quelque chose, mais ne renvoie aucune valeur. Ensuite. Nous avons vu
sa mise en œuvre dans l'opération
évoquée précédemment, mais la voici une fois de plus. Dans cet exemple, nous imprimons le prénom de chaque secteur d'activité
client. Gardez à l'esprit que pour
chacun d'entre eux, n'opérez sur les éléments qu'une fois qu'ils ont
parcouru le
reste du flux. Donc,
si nous plaçons un filtre avant
le fonctionnement du terminal , seuls les clients possédant moins de trois appareils obtiennent leur prénom et l'impriment. Enfin, savait-elle qu' une méthode normale peut également être
utilisée de manière groupée ? Prenez cette méthode, par exemple cela ne ressemble-t-il pas à une implémentation
destinée aux consommateurs, selon vous ? Il accepte un seul objet, fait quelque chose, mais ne renvoie
aucune valeur par la suite. Et en effet, nous pouvons utiliser cette
méthode dans notre ForEach, rendre plus lisible
au cours du processus. Et c'est tout. Pour chacun, il suffit d'effectuer
une action spécifiée pour chaque élément du flux qui traverse
le reste du flux.
7. Exploitation intermédiaire : carte: Une autre
opération intermédiaire de base, la carte. La carte est une
opération intermédiaire couramment utilisée pour mapper un type
d'objet à un autre. Mais il est généralement également utilisé
pour exécuter une logique métier. Ses entrées sont une fonction
qui, comme nous le savons maintenant, prend un objet de la classe a, fait quelque chose et renvoie un objet de classe b où les clauses a et
B peuvent être de la même classe. Voici un exemple de mappage
de la classe a à la classe B. Ici, nous avons un
objet client en entrée. Nous l'associons à une
chaîne composée de son prénom et de son
nom de famille avant de l'imprimer. Dans ce cas, nous mappons
de la classe a à la classe B, du client à la chaîne. Dans l'exemple suivant, nous avons un objet client en tant qu' entrée sur son appareil mobile
au travail. Renvoyez ensuite le même objet
client, enrichissant
ainsi efficacement
votre objet lui-même. Dans ce cas, nous
cartographions d'un
client à l' autre et atteignons l'
objet en cours de route. Notez que puisque le corps Lambda contient
deux instructions, j'ai dû ajouter les crochets
et renvoyer le mot clé. Enfin, comme pour toute opération
intermédiaire, il est possible d'avoir plusieurs opérations mathématiques
dans le même flux.
8. Opérations intermédiaires : flatMap: Ensuite, FlatMap. Comme son nom l'indique, FlatMap est similaire à la carte. Il s'agit d'une
opération intermédiaire couramment utilisée pour mapper un type
d'objet à un autre. À la différence près que FlatMap fonctionne sur des relations
un-à-plusieurs. Son entrée est également une fonction, mais une restriction est
imposée à l'objet renvoyé. Un flux doit être renvoyé. Nous voyons ici la
signature de la méthode map et FlatMap côte à côte pour vous
montrer la différence. Alors que les deux attendent la fonction, FlatMap s'attend
à ce que la valeur r soit de type chaîne. Voyons ce qu'il
fait et en quoi il
diffère de cela. Dans nos exemples, nous avons
utilisé l'objet client, qui contient une liste d'appareils. Que
se passerait-il selon vous si nous utilisions l'opération cartographique pour convertir chaque client
à ses appareils ? Comme vous pouvez le voir dans la sortie, mappage d'un client
vers une liste d'appareils donne lieu à un flux
de listes d'appareils. Une fois imprimées, ces listes
sont imprimées une par une. C'est peut-être quelque chose dont vous avez besoin pour votre cas d'utilisation fonctionnel. Mais le plus souvent, vous vous intéressez à
tous les appareils plutôt qu'à des
listes distinctes d'appareils. C'est là qu'intervient FlatMap. Comme je l'ai déjà dit. Flatmap impose une restriction sur l'objet
de retour de la fonction. Vous pouvez voir que le lambda
a légèrement changé pour FlatMap et renvoie maintenant
le périphérique sous forme de flux. Au lieu d'une liste. Notez dans les sorties
que les appareils sont désormais imprimés un par un
au lieu de liste par liste. La clé ici est que
FlatMap attend des flux sous forme résultats qui sont ensuite nouveau
aplatis en un
seul flux. Une fois de plus ensemble. Vous pouvez désormais
voir clairement la différence entre l'opération map et
FlatMap. En résumé, les cartes
doivent être utilisées lors de la conversion d'objets
avec une relation biunivoque. Alors que FlatMap
doit être utilisé lors conversion d'objets avec
une relation un-à-plusieurs. Lorsque vous utilisez FlatMap, la valeur de retour est
un flux d'objets.
9. Opérations intermédiaires : séquentiel et parallèle: Deux opérations sur la même
pièce, séquentielles et parallèles. séquentielles et parallèles sont
toutes deux des opérations intermédiaires qui rendent le flux complet séquentiel ou parallèle
respectivement. Comme il s'agit d'opérations
intermédiaires, elles peuvent être ajoutées
simultanément au flux , même plusieurs fois. Peu importe où se situe
l'
opération dans le flux. L'ensemble du flux est
séquentiel ou parallèle. Pas un peu des deux. Gardez à l'esprit que la dernière opération séquentielle
ou parallèle mentionnait l'industrie, celle qui est réellement utilisée. Cela signifie que ce flux est exactement le même
que celui-ci. Un flux est séquentiel
par défaut, ce qui signifie que les éléments
sont exécutés dans l'ordre dans lequel ils apparaissent
dans la collection américaine. Cela signifie également que
ces flux ont la même sortie. Comme tu peux le voir. en résulte une impression
de un à dix dans l'ordre avec ou sans l'opération
séquentielle. , lorsque nous changeons cela en parallèle, Cependant, lorsque nous changeons cela en parallèle, comme vous pouvez le constater, nous obtenons un résultat différent à
chaque fois que nous exécutons le Stream. Stream est exécuté en
mode multithread, ce qui signifie que le travail effectué est réparti entre
différentes exécutions. Les prétendues menaces. Gardez à l'esprit que le fait de faire fonctionner
un flux en parallèle ne
signifie pas automatiquement que le flux peut être exécuté en toute sécurité. En tant que développeur, vous devez vous assurer que votre
code fonctionne exactement de la même manière, 1236 ou quelles que soient les menaces. Comme il ne veut pas. Une autre chose à garder à
l'esprit lorsque vous exécutez des tâches en parallèle est que cela ne signifie pas nécessairement que le
travail est effectué plus rapidement. créer quelque chose de
multithread vous devez diviser
le travail en plusieurs parties, créer une exécution
pour chaque partie. Travail délégué, regroupez les
différents résultats en un seul. Cela entraîne
une surcharge lors l'
exécution du code ou du
flux, dans notre cas, ce qui ne sera bénéfique si vous avez suffisamment d'éléments dans votre flux ou si votre flux
est très gourmand en calcul. En résumé, les opérations séquentielles
et parallèles vous
permettent de rendre rapidement l'ensemble du flux
séquentiel ou parallèle. exécutant un flux en parallèle, vous devez, en tant que développeur, vous
assurer que le code
est sécurisé par thread.
10. Exploitation intermédiaire : un aperçu: Passons à une
question simple avant passer aux plus complexes. Pq. Pq est une opération
intermédiaire qui
vous permet littéralement de jeter un coup d'œil dans les
coulisses lors de l'
exécution d'une chaîne. Son utilisation principale est le débogage
et l'enregistrement de ses entrées. En tant que consommateur, cela
signifie qu'il reçoit une valeur et en fait quelque chose sans qu'il y
ait de valeur de retour. Bien qu'il soit possible de modifier les données pendant les périodes de pointe, vous prenez le risque de le faire. En fonction de votre
version de Java et du fait que le fonctionnement de
votre terminal
nécessite ou non fait que le fonctionnement de
votre terminal de traiter les
objets de la chaîne. Le code contenu dans Peek
peut être exécuté ou non. Soyez très prudent
lorsque vous utilisez Peak à des fins autres que le
débogage et la journalisation. Voici un exemple de son utilisation. Dans cet exemple, nous utilisons
peak pour imprimer le nom d'
un appareil avant de continuer mapper aux détails de sa commande, collecter les éventuels traitements
ultérieurs. L'un des résultats de ce flux
est une liste des détails des commandes. Grâce au pic de fonctionnement, nous pouvons obtenir une certaine journalisation avec un appareil que les objets utilisent
pour les résultats. Et j'ai vu que le pic est simplement un moyen de faire de
l'exploitation pendant un ruisseau. Vous pouvez l'utiliser pour modifier
des données, mais c'est risqué Je vous le déconseille
donc
si vous n'êtes pas encore
familiarisé avec les streams.
11. Exploitation du terminal : collecte: Notre deuxième
opération de terminal, Collect. Collect est une
opération de terminal qui collecte tous les éléments d'
un flux dans quelque chose. Il est couramment utilisé pour placer les éléments résultants d'
un flux dans une liste. Il existe deux implémentations
pour celle-ci. La première prévoit
une implémentation de l'interface du
collecteur. Cependant, il ne s'agit pas d'une
interface fonctionnelle et ne peut donc pas être réécrite
en tant qu'expression lambda. Heureusement pour nous, oui, Lava a eu la
gentillesse de fournir
aux collectionneurs des
clusters contenant toutes sortes de méthodes utiles. Nombre d'entre elles dépassent le
cadre de cet atelier. Mais il y en a une
que vous
utiliserez fréquemment pour les collectionneurs et deux listes. Comme on pouvait s'y attendre. Cela renvoie une implémentation de l'interface du collecteur qui collecte tous les éléments de la chaîne dans une
liste et la renvoie. Personnellement, je l'utilise 190, 9 % des fois où j'ai
besoin de collecter quelque chose et je m'attends
à ce que vous viviez la même chose. Mais pour comprendre un peu mieux
ce qu'il fait, passons en revue la
deuxième implémentation. Celui-ci attend un fournisseur
et deux des consommateurs. Le document Java nous donne un bon
aperçu de ce qu'il fait. Le fournisseur
nous fournit
ce que nous attendons
de l'opération de collecte. Ensuite, le premier
consommateur de vélo est
habitué à consommer un élément du
flux pour obtenir ces résultats. Cela se poursuit jusqu'à ce que
tous les éléments
du flux ou soient consommés
dans les résultats finaux. Cela ne nous montre pas ce que fait
le deuxième consommateur bi
à le combiner,
mais c' est
parce que le combineur n'
est nécessaire que lorsque le
flux est diffusé en parallèle. Dans ce cas, vous pouvez avoir deux fils de discussion ou plus
en commençant par le fournisseur. Une fois toutes les menaces éliminées, les résultats de ces
threads doivent être combinés en un seul résultat, exactement à quoi sert un
combineur. Mettons-le en pratique. En utilisant un fournisseur et
deux par les consommateurs. Je vais répliquer
la collecte des éléments clients
dans un flux. Nous allons commencer par le fournisseur. Quand les appels obtiendront la liste vide dans laquelle nous mettrons tous les éléments du flux. Ensuite, nous avons besoin d'un consommateur de
vélo qui accumule tous les éléments de la chaîne dans la liste des fournitures. Cela montre clairement que notre résultat est bien
cette liste et que chaque élément client
du stream est accumulé
dans une liste définie. Dans le cas d'un flux séquentiel, ce sera la fin de celui-ci. Mais pour permettre un traitement
parallèle, il
faudra une version finale par le consommateur qui combine deux
résultats en un seul. En utilisant cela par le consommateur, nous ajoutons
les éléments du deuxième résultat
au premier. Cette opération est répétée par
le flux jusqu'à ce que tous les résultats des menaces soient
fusionnés en un seul. Ici, ils sont renseignés dans
l'opération de collecte. Et grâce à cela, vous savez comment créer
vos propres collections sur mesure. Je le répète, il existe deux implémentations de
la coopération de collecte. La première attend
un collecteur pour lequel
Java a préparé des options pour vous à l'aide de la clause
collectors. Le second attend un
fournisseur et lie les consommateurs, ce qui le rend beaucoup
plus personnalisable. Vous utiliserez la collection
préparée de cette classe la
plupart du temps. Mais au moins maintenant tu
sais comment ça fonctionne.
12. Exploitation du terminal : réduire: Le dernier opérateur
discutera de la réduction. Reduce est une
opération de terminal qui peut être utilisée pour réduire tous les éléments d'un
flux en un seul objet. C'est un peu comme une
opération de collecte dont nous avons parlé. Mais tandis que collect
applique tous les éléments
du flux à un
conteneur immuable comme une liste ou un ensemble. Reduce ne
collecte pas mais applique tous les éléments à un seul
objet. L'identité. Réduisez, prend son identité, accumule des éléments
dans l'identité, puis combine plusieurs résultats en un seul au
cas où tout serait exécuté en parallèle. Réduire est l'
opération la plus difficile à appréhender. Alors ne vous sentez pas mal si vous
ne recevez pas tout cela en même temps. Prenez simplement votre temps pour
suivre cette section et essayez les exercices à
la fin du cours. S'il vous reste des questions, hésitez pas à les poser
via la plateforme. Très bien, plongeons-nous. Deep Reduce attend
une valeur
de départ appelée fonction d'identité qui est utilisée pour cumuler et
un opérateur binaire utilisé pour combiner les résultats
issus de threads distincts. Le chien alpha nous donne un bel
aperçu de ce qu'il fait. Cette identité nous donne
le point de départ des résultats. Il doit s'agir d'une feuille blanche et vide, telle sorte que l'ajout de la
valeur du flux à cette identité ait ce résultat
et soit modifié en tant que produit. Ensuite, pour chaque élément
du flux, il est accumulé dans la valeur résultante à
l'aide de la fonction by. Tout comme pour collecter, cela ne nous montre pas ce que fait
l'opérateur binaire,
le combineur. Il en va de même ici. Le combineur est uniquement utilisé
pour combiner les résultats de plusieurs threads dans le
cas où le flux est exécuté en parallèle. Mettons-le en pratique. Pour notre exemple, nous allons, nous allons sélectionner tous les
clients dans un entier représentant le nombre total d' appareils détenus par ces
clients ensemble. Notre identité doit
être un entier. Par conséquent, nous voulons
sortir de cette tendance. En ce qui concerne la valeur. N'oubliez pas que l'ajout
d'un résultat à l'identité doit
entraîner une modification en tant que produit. Dans notre cas, nous devrons
additionner la taille de toutes les listes d'appareils pour obtenir
nos résultats finaux. Quelle valeur de l'
identité signifie que identité plus la taille de la liste des
appareils est égale à deux. L'appareil,
c'est vrai, zéro. Notre identité
sera donc la suivante. Ensuite, nous avons besoin d'une fonction qui produit un élément du
flux dans cette identité. Le premier générique utilisé
dans la fonction by est un entier qui représente la valeur actuelle
des résultats. Le sous-total, si vous voulez. La deuxième utilisation des génériques est
l'élément du flux, qui sera réduit
au sous-total. La troisième
utilisation générique est le type du résultat de l'
opération, un entier. Ce troisième terme générique doit être identique
au premier, ce qui est logique puisque le premier terme générique
représente le sous-total. Dans le cas d'un flux séquentiel, ce serait la fin de celui-ci. Mais pour permettre un traitement
parallèle, il
faudra un opérateur binaire pour combiner deux résultats en un seul. À l'aide de cet opérateur binaire, nous combinons les résultats
de deux threads. Ceci est répété par
le flux jusqu'à ce que tous les résultats des threads soient
fusionnés en un seul. Ici, ils sont intégrés à
l'opération de réduction. Je le répète, nous
partons d'une table rase
vide en tant qu'identité
zéro. Dans notre cas. Nous ajoutons ensuite la taille
de la liste des appareils de chaque élément du
flux à cette identité. Si le flux est exécuté en parallèle, nous les combinons
pour ajouter deux sous-totaux en un seul jusqu'à ce qu'il ne nous reste qu'
un seul résultat. Dans notre exemple, nous avons réduit nos objets complexes
en un seul entier. Mais la réduction peut également
être utilisée pour réduire tous les éléments d'un flux en
un seul objet complexe. Par exemple, nous pourrions réduire nos clients à un seul
client contenant nos informations. Mais je vais laisser
celui-ci dans
le cadre des exercices que vous
pouvez faire vous-même.
13. Résumé et mot après-vente: Nous sommes arrivés à la
fin de ce cours. Résumons pour voir
ce que nous avons appris au notre transition vers l'API
Java eight Streams. Nous avons commencé par
apprendre à quoi
servent les flux et comment ils fonctionnent. Nous avons ensuite expliqué comment créer une
expression lambda à partir d' une classe interne anonyme grâce
à des interfaces fonctionnelles. Nous avons brièvement discuté, mais les interfaces
fonctionnelles le sont, et de celles que vous utilisez
couramment lorsque vous travaillez avec des flux. Enfin, nous avons passé en revue les opérations intermédiaires
et terminales couramment utilisées. Merci d'avoir
regardé ce cours. J'espère que vous en avez suffisamment appris
sur les streams pour reconnaître les situations dans lesquelles vous pouvez
et êtes capable de les utiliser. Si vous souhaitez m'aider à
améliorer ce cours et nous
dire si vous l'
avez trouvé utile ou non. Je vous serais reconnaissant de
laisser un commentaire. Comme promis. Je vous ai préparé quelques
exercices pour voir si vous pouvez appliquer les connaissances apprises
au cours de ce cours. Chaque exercice comporte une demande, un résultat attendu pour que vous
puissiez vérifier si vous l'avez bien fait. S'il y a quelque chose de
flou sur ce cours, des exercices déjà
fournis, n'hésitez pas à m'envoyer un
message avec vos questions. Je vais vous aider
de mon mieux. Encore une fois. Merci de votre attention
et jusqu'à la prochaine fois.