Introduksjon til Protonpack

1. Oversikt

I denne opplæringen vil vi se på de viktigste funksjonene i Protonpack, som er et bibliotek som utvider standarden Strøm API ved å legge til litt gratis funksjonalitet.

Se denne oppskriften her for å oppdage grunnleggende Java Strøm API.

2. Maven avhengighet

For å bruke Protonpack-biblioteket, må vi legge til en avhengighet i vårt pom.xml fil:

 com.codepoetics protonpack 1.15 

Se etter den nyeste versjonen på Maven Central.

3. StreamUtils

Dette er hovedklassen som utvider Java-standarden Strøm API.

Alle metodene som er diskutert her er mellomoperasjoner, noe som betyr at de endrer a Strøm men utløser ikke behandlingen.

3.1. taMens () og ta til ()

taMens () tar verdier fra kildestrømmen så lenge de oppfyller den leverte tilstanden:

Stream streamOfInt = Stream .iterate (1, i -> i + 1); Listresultat = StreamUtils .takeWhile (streamOfInt, i -> i <5) .collect (Collectors.toList ()); assertThat (resultat). inneholder (1, 2, 3, 4);

Omvendt, ta til () tar verdier til en verdi oppfyller den leverte tilstanden og stopper deretter:

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

I Java 9 og fremover, taMens () er en del av standarden Strøm API.

3.2. glidelås()

glidelås() tar to eller tre strømmer som inngangs- og kombinasjonsfunksjon. Metoden tar en verdi fra samme posisjon til hver strøm og overfører den til kombinatoren.

Det gjør det til en av bekkene går tom for verdier:

String [] klubber = {"Juventus", "Barcelona", "Liverpool", "PSG"}; String [] spillere = {"Ronaldo", "Messi", "Salah"}; Sett zippedFrom2Sources = StreamUtils .zip (stream (klubber), stream (spillere), (klubb, spiller) -> klubb + "" + spiller). Samle (Collectors.toSet ()); assertThat (zippedFrom2Sources) .contains ("Juventus Ronaldo", "Barcelona Messi", "Liverpool Salah"); 

Tilsvarende en overbelastet glidelås() som tar tre kilder stream:

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

3.3. zipWithIndex ()

zipWithIndex () tar verdier og zip hver verdi med indeksen for å lage en strøm av indekserte verdier:

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

3.4. slå sammen()

slå sammen() fungerer med flere kildestrømmer og en kombinator. Den tar verdien av den samme indeksposisjonen fra hver kildestrøm og overfører den til kombinereren.

Metoden fungerer ved å ta 1 verdi fra samme indeks fra hver strøm i rekkefølge, fra og med frø verdi.

Deretter sendes verdien til kombinatoren, og den resulterende kombinerte verdien blir matet tilbake til kombinatoren for å skape neste verdi:

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"); Sett slått sammen = StreamUtils.merge (() -> "", (valOne, valTwo) -> valOne + "" + valTwo, streamOfClubs, streamOfPlayers, streamOfLighte) .collect (Collectors.toSet ()); hevder at (fusjonert). inneholder ("Juventus Ronaldo Serie A", "Barcelona Messi La Liga", "Liverpool Salah Premier League", "PSG");

3.5. mergeToList ()

mergeToList () tar flere strømmer som input. Den kombinerer verdien av den samme indeksen 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 ()oppretter alternative verdier hentet fra flere strømmer ved hjelp av a velgeren.

Metoden gir et sett som inneholder en verdi fra hver strøm til velgeren, og velgeren velger en verdi.

Deretter vil den valgte verdien bli fjernet fra settet og erstattet med den neste verdien som den valgte verdien stammer fra. Denne iterasjonen fortsetter til alle kilder går tom for verdier.

Det neste eksemplet bruker interleave () for å lage vekslende verdier med en round-robin strategi:

Stream streamOfClubs = Stream .of ("Juventus", "Barcelona", "Liverpool"); Stream streamOfPlayers = Stream .of ("Ronaldo", "Messi"); Stream streamOfLgue = Stream .of ("Serie A", "La Liga"); List interleavedList = StreamUtils .interleave (Selectors.roundRobin (), streamOfClubs, streamOfPlayers, streamOfLighte) .collect (Collectors.toList ()); assertThat (interleavedList) .hasSize (7) .containsAkkurat ("Juventus", "Ronaldo", "Serie A", "Barcelona", "Messi", "La Liga", "Liverpool"); 

Vær oppmerksom på at ovennevnte kode er for opplæringsformål fordi round-robin velgeren er levert av biblioteket som Selectors.roundRobin ().

3.7. skipUntil () og skipWhile ()

skipUntil () hopper over verdiene til en verdi oppfyller betingelsen:

Heltall [] tall = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; Liste skippedUntilGreaterThan5 = StreamUtils .skipUntil (stream (tall), i -> i> 5) .collect (Collectors.toList ()); assertThat (hoppet overtilGreaterThan5). inneholder nøyaktig (6, 7, 8, 9, 10); 

I motsetning, skipWhile ()hopper over verdiene mens verdiene oppfyller betingelsen:

Heltall [] tall = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; List skippedWhileLessThanEquals5 = StreamUtils .skipWhile (stream (numbers), i -> i <= 5 ||) .collect (Collectors.toList ()); assertThat (hoppet over MensLessThanEquals5). inneholder nøyaktig (6, 7, 8, 9, 10); 

En viktig ting om skipWhile () er at den vil fortsette å streame etter at den fant den første verdien som ikke oppfyller betingelsen:

Liste skippedWhileGreaterThan5 = StreamUtils .skipWhile (stream (tall), i -> i> 5) .collect (Collectors.toList ()); assertThat (skippedWhileGreaterThan5) .containsAkkurat (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 

I Java 9 og fremover, slipp mens() i standard Strøm API gir samme funksjonalitet som skipWhile ().

3.8. brette()

brette() genererer en potensielt uendelig strøm ved å bruke en tilpasset generator til en frøverdi og deretter til hver genererte verdi - strømmen kan avsluttes ved å returnere Valgfritt. Lett ():

Stream utfoldet = StreamUtils .unfold (2, i -> (i <100)? Optional.of (i * i): Optional.empty ()); assertThat (unfolded.collect (Collectors.toList ())). inneholder nøyaktig (2, 4, 16, 256);

3.9. vindu ()

vindu ()oppretter flere delmengder av kildestrøm som en strøm av Liste. Metoden tar en kildestrøm, vindusstørrelse og hopp over verdi som parameter.

De Liste lengden er lik vindustørrelse, mens skip-verdi bestemmer hvor delsettet begynner i forhold til forrige delsett:

Heltall [] tall = {1, 2, 3, 4, 5, 6, 7, 8}; List windowedWithSkip1 = StreamUtils .windowed (stream (tall), 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 )); 

I tillegg er det siste vinduet garantert av ønsket størrelse, som vi kan se i følgende eksempel:

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

3.10. aggregat ()

Det er to aggregat () metoder som fungerer ganske annerledes.

Den første aggregat () grupperer sammen elementer av lik verdi i henhold til et gitt predikat:

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

Predikatet mottar verdiene på en sammenhengende måte. Derfor vil ovennevnte gi et annet resultat hvis nummeret ikke bestilles.

På den annen side, den andre aggregat () er ganske enkelt vant til gruppere elementer fra kildestrømmen i grupper av ønsket størrelse:

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

3.11. aggregateOnListCondition ()

aggregateOnListCondition () grupperer verdier basert på predikat og nåværende aktiv gruppe. Predikatet får den aktive gruppen som en Liste og neste verdi. Den må da avgjøre om gruppen skal fortsette eller starte en ny gruppe.

Følgende eksempel løser et krav om å gruppere sammenhengende heltallverdier i en gruppe, hvor summen av verdier i hver gruppe ikke må være større enn 5:

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

4. Strømbar

En forekomst av Strøm kan ikke gjenbrukes. Av denne grunn, Strømbar gir gjenbrukbare strømmer ved å pakke inn og utsette de samme metodene som Strøm:

Streamable s = Streamable.of ("a", "b", "c", "d"); Liste samlet1 = s.collect (Collectors.toList ()); Liste samlet2 = s.collect (Collectors.toList ()); assertThat (samlet1) .hasSize (4); assertThat (samlet2) .hasSize (4);

5. CollectorUtils

CollectorUtils utfyller standarden Samlere ved å legge til flere nyttige samlermetoder.

5.1. maxBy () og minBy ()

maxBy ()finner den maksimale verdien i en strøm ved hjelp av den medfølgende projeksjonslogikken:

Strømklubber = Stream.of ("Juventus", "Barcelona", "PSG"); Valgfritt lengste navn = clubs.collect (CollectorUtils.maxBy (streng :: lengde)); assertThat (longestName) .contains ("Barcelona");

I motsetning, minBy ()finner minimumsverdien ved hjelp av den medfølgende projeksjonslogikken.

5.2. unik()

De unik() samler gjør en veldig enkel ting: den returnerer den eneste verdien hvis en gitt strøm har nøyaktig 1 element:

Stream singleElement = Stream.of (1); Valgfritt unikt = singleElement.collect (CollectorUtils.unique ()); assertThat (unik). inneholder (1); 

Ellers, unik() vil kaste et unntak:

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

6. Konklusjon

I denne artikkelen lærte vi hvordan Protonpack-biblioteket utvider Java Stream API for å gjøre det enklere å bruke. Det legger til nyttige metoder som vi ofte bruker, men som mangler i standard API.

Fra og med Java 9 vil noe av funksjonaliteten som tilbys av Protonpack være tilgjengelig i standard Stream API.

Som vanlig kan du finne koden på Github.


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