Introduktion til Protonpack

1. Oversigt

I denne vejledning ser vi på de vigtigste funktioner i Protonpack, som er et bibliotek, der udvider standarden Strøm API ved at tilføje nogle gratis funktioner.

Se denne opskrivning her for at finde de grundlæggende elementer i Java Strøm API.

2. Maven-afhængighed

For at bruge Protonpack-biblioteket skal vi tilføje en afhængighed i vores pom.xml fil:

 com.codepoetics protonpack 1.15 

Se efter den nyeste version på Maven Central.

3. StreamUtils

Dette er hovedklassen, der udvider Java's standard Strøm API.

Alle de her diskuterede metoder er mellemliggende operationer, hvilket betyder, at de ændrer a Strøm men udløser ikke behandlingen.

3.1. tageMens () og tageUntil ()

tageMens () tager værdier fra kildestrømmen så længe de opfylder den leverede betingelse:

Stream streamOfInt = Stream .iterate (1, i -> i + 1); Listeresultat = StreamUtils .takeWhile (streamOfInt, i -> i <5) .collect (Collectors.toList ()); hævder, at (resultat). indeholder (1, 2, 3, 4);

Omvendt tage til () tager værdier indtil en værdi opfylder den leverede betingelse og stopper derefter:

Stream streamOfInt = Stream .iterate (1, i -> i + 1); Listeresultat = StreamUtils .takeUntil (streamOfInt, i -> i> = 5) .collect (Collectors.toList ()); assertThat (resultat) .containsExactly (1, 2, 3, 4);

I Java 9 og fremefter tageMens () er en del af standarden Strøm API.

3.2. lynlås ()

lynlås () tager to eller tre streams som input og combiner-funktion. Metoden tager en værdi fra den samme position for hver strøm og sender den til kombinereren.

Det gør det, indtil en af ​​streams løber tør for værdier:

String [] klubber = {"Juventus", "Barcelona", "Liverpool", "PSG"}; String [] spillere = {"Ronaldo", "Messi", "Salah"}; Indstil zippedFrom2Sources = StreamUtils .zip (stream (klubber), stream (spillere), (klub, spiller) -> klub + "" + spiller). Samle (Collectors.toSet ()); hævder, at (zippedFrom2Sources). indeholder ("Juventus Ronaldo", "Barcelona Messi", "Liverpool Salah"); 

Tilsvarende en overbelastet lynlås () der tager tre kilder stream:

String [] ligaer = {"Serie A", "La Liga", "Premier League"}; Indstil zippedFrom3Sources = StreamUtils .zip (stream (klubber), stream (spillere), stream (ligaer), (klub, spiller, liga) -> klub + "" + spiller + "" + liga) .collect (Collectors.toSet ( )); hævder, at (zippedFrom3Sources). indeholder ("Juventus Ronaldo Serie A", "Barcelona Messi La Liga", "Liverpool Salah Premier League");

3.3. zipWithIndex ()

zipWithIndex () tager værdier og zip hver værdi med sit indeks for at oprette en strøm af indekserede værdier:

Stream streamOfClubs = Stream .of ("Juventus", "Barcelona", "Liverpool"); Sæt zipsWithIndex = StreamUtils .zipWithIndex (streamOfClubs) .collect (Collectors.toSet ()); assertThat (zipsWithIndex) .contains (Indexed.index (0, "Juventus"), Indexed.index (1, "Barcelona"), Indexed.index (2, "Liverpool"));

3.4. fusionere()

fusionere() fungerer med flere kildestrømme og en combiner. Det tager værdien af ​​den samme indeksposition fra hver kildestrøm og overfører den til kombinereren.

Metoden fungerer ved at tage 1 værdi fra det samme indeks fra hver strøm i rækkefølge, startende fra frø værdi.

Derefter sendes værdien til kombinereren, og den resulterende kombinerede værdi føres tilbage til kombinereren for at skabe den næste værdi:

Stream streamOfClubs = Stream .of ("Juventus", "Barcelona", "Liverpool", "PSG"); Stream streamOfPlayers = Stream .of ("Ronaldo", "Messi", "Salah"); Stream streamOfLgue = Stream .of ("Serie A", "La Liga", "Premier League"); Set merged = StreamUtils.merge (() -> "", (valOne, valTwo) -> valOne + "" + valTwo, streamOfClubs, streamOfPlayers, streamOfLighte) .collect (Collectors.toSet ()); hævder, at (fusioneret). indeholder ("Juventus Ronaldo Serie A", "Barcelona Messi La Liga", "Liverpool Salah Premier League", "PSG");

3.5. mergeToList ()

mergeToList () tager flere streams som input. Det kombinerer værdien af ​​det samme indeks fra hver strøm til en Liste:

Stream streamOfClubs = Stream .of ("Juventus", "Barcelona", "PSG"); Stream streamOfPlayers = Stream .of ("Ronaldo", "Messi"); Strøm mergedStreamOfList = StreamUtils .mergeToList (streamOfClubs, streamOfPlayers); Liste mergedListOfList = mergedStreamOfList .collect (Collectors.toList ()); assertThat (mergedListOfList.get (0)) .containsExactly ("Juventus", "Ronaldo"); assertThat (mergedListOfList.get (1)) .containsExactly ("Barcelona", "Messi"); assertThat (mergedListOfList.get (2)) .containsExactly ("PSG");

3.6. interleave ()

interleave ()opretter alternative værdier taget fra flere streams ved hjælp af a vælger.

Metoden giver et sæt, der indeholder en værdi fra hver strøm til vælger, og vælger vælger en værdi.

Derefter fjernes den valgte værdi fra sættet og erstattes med den næste værdi, hvorfra den valgte værdi stammer. Denne iteration fortsætter, indtil alle kilder løber tør for værdier.

Det næste eksempel bruger interleave () for at oprette skiftende værdier med en runde Robin strategi:

Stream streamOfClubs = Stream .of ("Juventus", "Barcelona", "Liverpool"); Stream streamOfPlayers = Stream .of ("Ronaldo", "Messi"); Stream streamOfLgue = Stream .of ("Serie A", "La Liga"); Liste interleavedList = StreamUtils .interleave (Selectors.roundRobin (), streamOfClubs, streamOfPlayers, streamOfLgue) .collect (Collectors.toList ()); hævder, at (interleavedList) .har størrelse (7). indeholder nøjagtigt ("Juventus", "Ronaldo", "Serie A", "Barcelona", "Messi", "La Liga", "Liverpool"); 

Vær opmærksom på, at ovenstående kode er til tutorialsformål, fordi round-robin vælger leveres af biblioteket som Selectors.roundRobin ().

3.7. skipUntil () og skipWhile ()

skipUntil () springer værdierne over indtil en værdi opfylder betingelsen:

Heltal [] tal = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; Liste skippedUntilGreaterThan5 = StreamUtils .skipUntil (stream (tal), i -> i> 5) .collect (Collectors.toList ()); assertThat (sprunget overtilGreaterThan5). indeholder nøjagtigt (6, 7, 8, 9, 10); 

I modsætning, skipWhile ()springer værdierne over, mens værdierne opfylder betingelsen:

Heltal [] tal = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; Liste skippedWhileLessThanEquals5 = StreamUtils .skipWhile (stream (tal), i -> i <= 5 ||) .collect (Collectors.toList ()); assertThat (skippedWhileLessThanEquals5) .containsExactly (6, 7, 8, 9, 10); 

En vigtig ting ved skipWhile () er, at den fortsætter med at streame, efter at den har fundet den første værdi, der ikke opfylder betingelsen:

Liste skippedWhileGreaterThan5 = StreamUtils .skipWhile (stream (tal), i -> i> 5) .collect (Collectors.toList ()); assertThat (sprungetWhileGreaterThan5). indeholder nøjagtigt (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 

I Java 9 og fremefter dråbe mens() i standard Strøm API giver den samme funktionalitet som skipWhile ().

3.8. udfolde ()

udfolde () genererer en potentielt uendelig strøm ved at anvende en brugerdefineret generator til en frøværdi og derefter til hver genererede værdi - strømmen kan afsluttes ved at returnere Valgfri. Let ():

Stream udfoldet = StreamUtils .unfold (2, i -> (i <100)? Optional.of (i * i): Optional.empty ()); assertThat (unfolded.collect (Collectors.toList ())). indeholder Nøjagtigt (2, 4, 16, 256);

3.9. vinduesvindue ()

vinduesvindue ()opretter flere undersæt af kildestrøm som en strøm af Liste. Metoden tager en kildestrøm, vinduesstørrelse og spring værdi over som parameter.

Det Liste længde er lig med vinduestørrelse, mens skip-værdi bestemmer, hvor delsættet begynder i forhold til det forrige delsæt:

Heltal [] tal = {1, 2, 3, 4, 5, 6, 7, 8}; List windowedWithSkip1 = StreamUtils .windowed (stream (tal), 3, 1) .collect (Collectors.toList ()); assertThat (windowedWithSkip1) .containsExactly (asList (1, 2, 3), asList (2, 3, 4), asList (3, 4, 5), asList (4, 5, 6), asList (5, 6, 7 )); 

Derudover er det sidste vindue garanteret af den ønskede størrelse, som vi kan se i følgende eksempel:

Liste windowedWithSkip2 = StreamUtils.windowed (stream (tal), 3, 2) .collect (Collectors.toList ()); assertThat (windowedWithSkip2) .containsExactly (asList (1, 2, 3), asList (3, 4, 5), asList (5, 6, 7)); 

3.10. samlet()

Der er to samlet() metoder, der fungerer helt anderledes.

Den første samlet() grupperer elementer af samme værdi i henhold til et givet predikat:

Heltal [] tal = {1, 2, 2, 3, 4, 4, 4, 5}; Liste aggregeret = StreamUtils .aggregate (Arrays.stream (numbers), (int1, int2) -> int1.compareTo (int2) == 0) .collect (Collectors.toList ()); assertThat (aggregeret) .containsExactly (asList (1), asList (2, 2), asList (3), asList (4, 4, 4), asList (5)); 

Prædikatet modtager værdierne sammenhængende. Derfor giver ovenstående et andet resultat, hvis nummeret ikke bestilles.

På den anden side den anden samlet() er simpelthen vant til gruppere elementer fra kildestrømmen i grupper med den ønskede størrelse:

Liste aggregatedFixSize = StreamUtils .aggregate (stream (numbers), 5) .collect (Collectors.toList ()); assertThat (aggregatedFixSize) .containsExactly (asList (1, 2, 2, 3, 4), asList (4, 4, 5)); 

3.11. aggregateOnListCondition ()

aggregateOnListCondition () grupperer værdier baseret på prædikat og aktuel aktiv gruppe. Prædikatet får den aktuelt aktive gruppe som en Liste og den næste værdi. Derefter skal det afgøre, om gruppen skal fortsætte eller starte en ny gruppe.

Følgende eksempel løser et krav om at gruppere sammenhængende heltalværdier sammen i en gruppe, hvor summen af ​​værdier i hver gruppe ikke må være større end 5:

Heltal [] tal = {1, 1, 2, 3, 4, 4, 5}; Strøm aggregeret = StreamUtils .aggregateOnListCondition (stream (numbers), (currentList, nextInt) -> currentList.stream (). mapToInt (Integer :: intValue) .sum () + nextInt <= 5); assertThat (aggregeret) .containsExactly (asList (1, 1, 2), asList (3), asList (4), asList (4), asList (5));

4. Kan streames

En forekomst af Strøm kan ikke genbruges. Af denne grund, Kan streames giver genanvendelige streams ved at indpakke og udsætte de samme metoder som Strøm:

Streamable s = Streamable.of ("a", "b", "c", "d"); Liste indsamlet1 = s.collect (Collectors.toList ()); Liste indsamlet2 = s.collect (Collectors.toList ()); hævder, at (samlet1) .hasstørrelse (4); hævder, at (samlet2) .hasstørrelse (4);

5. CollectorUtils

CollectorUtils supplerer standarden Samlere ved at tilføje flere nyttige opsamlingsmetoder.

5.1. maxBy () og minBy ()

maxBy ()finder den maksimale værdi i en stream ved hjælp af den medfølgende projiceringslogik:

Stream klubber = Stream.of ("Juventus", "Barcelona", "PSG"); Valgfrit længste navn = clubs.collect (CollectorUtils.maxBy (streng :: længde)); assertThat (longestName) .contains ("Barcelona");

I modsætning, minBy ()finder minimumsværdien ved hjælp af den medfølgende projiceringslogik.

5.2. enestående()

Det enestående() samler gør en meget enkel ting: det returnerer den eneste værdi, hvis en given stream har nøjagtigt 1 element:

Stream singleElement = Stream.of (1); Valgfri unik = singleElement.collect (CollectorUtils.unique ()); assertThat (unik). indeholder (1); 

Ellers, enestående() kaster en undtagelse:

Stream multipleElement = Stream.of (1, 2, 3); assertThatExceptionOfType (NonUniqueValueException.class) .isThrownBy (() -> {multipleElement.collect (CollectorUtils.unique ());}); 

6. Konklusion

I denne artikel lærte vi, hvordan Protonpack-biblioteket udvider Java Stream API for at gøre det lettere at bruge. Det tilføjer nyttige metoder, som vi ofte bruger, men mangler i standard API.

Fra og med Java 9 vil nogle af funktionaliteterne fra Protonpack være tilgængelige i standard Stream API.

Som sædvanligt kan koden findes på Github.


$config[zx-auto] not found$config[zx-overlay] not found