Úvod do Protonpacku

1. Prehľad

V tomto výučbe sa pozrieme na hlavné funkcie Protonpack, čo je knižnica, ktorá rozširuje štandard Prúd API pridaním niektorých doplnkových funkcií.

V tomto návode sa dozviete ďalšie základné informácie o Java Prúd API.

2. Závislosť od Maven

Ak chcete používať knižnicu Protonpack, musíme do nášho pridať závislosť pom.xml spis:

 com.codepoetics protonpack 1.15 

Skontrolujte najnovšiu verziu na serveri Maven Central.

3. StreamUtils

Toto je hlavná trieda, ktorá rozširuje štandard Java Prúd API.

Všetky metódy tu diskutované sú prechodné operácie, čo znamená, že modifikujú a Prúd ale nespustí jeho spracovanie.

3.1. takeWhile () a takeUntil ()

takeWhile () preberá hodnoty zo zdrojového streamu pokiaľ spĺňajú dodanú podmienku:

Stream streamOfInt = Stream .iterate (1, i -> i + 1); Výsledok zoznamu = StreamUtils .takeWhile (streamOfInt, i -> i <5) .collect (Collectors.toList ()); tvrdiťTo (výsledok) .obsahuje (1, 2, 3, 4);

Naopak, takeUntil () berie hodnoty kým hodnota nesplní dodanú podmienku a potom sa zastaví:

Stream streamOfInt = Stream .iterate (1, i -> i + 1); Výsledok zoznamu = StreamUtils .takeUntil (streamOfInt, i -> i> = 5) .collect (Collectors.toList ()); tvrdiťTo (výsledok). obsahuje Presne (1, 2, 3, 4);

V prostredí Java 9 a ďalej, takeWhile () je súčasťou normy Prúd API.

3.2. PSČ()

PSČ() berie dva alebo tri prúdy ako vstup a funkciu kombinátora. Metóda vezme hodnotu z rovnakej polohy každého streamu a odovzdá ju kombinátoru.

Robí to dovtedy, kým jednému z prúdov nedôjde hodnota:

Reťazec [] kluby = {"Juventus", "Barcelona", "Liverpool", "PSG"}; Reťazec [] hráči = {"Ronaldo", "Messi", "Salah"}; Nastaviť zippedFrom2Sources = StreamUtils .zip (stream (kluby), stream (hráči), (klub, hráč) -> klub + "" + hráč) .collect (Collectors.toSet ()); assertThat (zippedFrom2Sources) .obsahuje ("Juventus Ronaldo", "Barcelona Messi", "Liverpool Salah"); 

Podobne preťažený PSČ() ktorý prenáša tri zdroje:

Reťazec [] ligy = {"Séria A", "La Liga", "Premier League"}; Nastaviť zippedFrom3Sources = StreamUtils .zip (prúd (kluby), prúd (hráči), prúd (ligy), (klub, hráč, liga) -> klub + "" + hráč + "" + liga). Zbierka (Collectors.toSet ( )); assertThat (zippedFrom3Sources) .obsahuje ("Juventus Ronaldo Serie A", "Barcelona Messi La Liga", "Liverpool Salah Premier League");

3.3. zipWithIndex ()

zipWithIndex () vezme hodnoty a zazipuje každú hodnotu pomocou jej indexu, aby vytvoril prúd indexovaných hodnôt:

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

3.4. zlúčiť()

zlúčiť() pracuje s viacerými zdrojovými prúdmi a kombinátorom. To vezme hodnotu rovnakej pozície indexu z každého zdrojového toku a odovzdá ju kombinátoru.

Metóda funguje tak, že sa z každého toku postupne vezme 1 hodnota z rovnakého indexu, počnúc od semienko hodnotu.

Potom sa hodnota odovzdá kombinátoru a výsledná kombinovaná hodnota sa vráti späť do kombinátora, aby sa vytvorila ďalšia hodnota:

Stream streamOfClubs = Stream .of ("Juventus", "Barcelona", "Liverpool", "PSG"); Stream streamOfPlayers = Stream .of ("Ronaldo", "Messi", "Salah"); Stream streamOfLellow = Stream .of ("Serie A", "La Liga", "Premier League"); Set merged = StreamUtils.merge (() -> "", (valOne, valTwo) -> valOne + "" + valTwo, streamOfClubs, streamOfPlayers, streamOfLleges) .collect (Collectors.toSet ()); assertThat (zlúčené) .obsahuje ("Juventus Ronaldo Serie A", "Barcelona Messi La Liga", "Liverpool Salah Premier League", "PSG");

3.5. mergeToList ()

mergeToList () prijíma viac vstupov. To kombinuje hodnotu rovnakého indexu z každého streamu do a Zoznam:

Stream streamOfClubs = Stream .of ("Juventus", "Barcelona", "PSG"); Stream streamOfPlayers = Stream .of ("Ronaldo", "Messi"); Prúd mergedStreamOfList = StreamUtils .mergeToList (streamOfClubs, streamOfPlayers); Zoznam 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. prekladať ()

prekladať ()vytvára alternatívne hodnoty prevzaté z viacerých prúdov pomocou a selektor.

Metóda dáva množinu obsahujúcu jednu hodnotu z každého toku do selektora selektor vyberie jednu hodnotu.

Potom bude vybratá hodnota odstránená z množiny a nahradená ďalšou hodnotou, z ktorej vybraná hodnota pochádza. Táto iterácia pokračuje, kým všetkým zdrojom nedôjde hodnota.

Nasledujúci príklad používa prekladať () vytvárať striedavé hodnoty s a každý s každým stratégia:

Stream streamOfClubs = Stream .of ("Juventus", "Barcelona", "Liverpool"); Stream streamOfPlayers = Stream .of ("Ronaldo", "Messi"); Stream streamOfLellow = Stream .of ("Séria A", "La Liga"); Zoznam interleavedList = StreamUtils .interleave (Selectors.roundRobin (), streamOfClubs, streamOfPlayers, streamOfLleges) .collect (Collectors.toList ()); assertThat (interleavedList) .hasSize (7). obsahuje Presne ("Juventus", "Ronaldo", "Séria A", "Barcelona", "Messi", "La Liga", "Liverpool"); 

Uvedomte si, že vyššie uvedený kód slúži len na účely výučby a je založený na princípe každý s každým selektor poskytuje knižnica ako Selectors.roundRobin ().

3.7. skipUntil () a skipWhile ()

skipUntil () preskočí hodnoty kým hodnota nespĺňa podmienku:

Celé číslo [] čísla = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; Zoznam skippedUntilGreaterThan5 = StreamUtils .skipUntil (stream (čísla), i -> i> 5) .collect (Collectors.toList ()); assertThat (skippedUntilGreaterThan5). obsahuje Presne (6, 7, 8, 9, 10); 

Naproti tomu skipWhile ()preskočí hodnoty, zatiaľ čo hodnoty vyhovujú podmienke:

Celé číslo [] čísla = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; Zoznam preskočenýWhileLessThanEquals5 = StreamUtils .skipWhile (prúd (čísla), i -> i <= 5 ||) .collect (Collectors.toList ()); assertThat (skippedWhileLessThanEquals5). obsahuje Presne (6, 7, 8, 9, 10); 

Jedna dôležitá vec skipWhile () je, že bude pokračovať v streamovaní, keď nájde prvú hodnotu, ktorá nespĺňa podmienku:

Zoznam vynechanýchWhileGreaterThan5 = StreamUtils .skipWhile (stream (čísla), i -> i> 5) .collect (Collectors.toList ()); assertThat (skippedWhileGreaterThan5). obsahuje Presne (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 

V prostredí Java 9 a ďalej, dropWhile() v štandarde Prúd API poskytuje rovnakú funkcionalitu ako skipWhile ().

3.8. rozvinúť ()

rozvinúť () vygeneruje potenciálne nekonečný prúd použitím vlastného generátora na počiatočnú hodnotu a potom na každú vygenerovanú hodnotu - prúd je možné ukončiť vrátením Optional.empty ():

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

3.9. okenné ()

okenné ()vytvára viac podskupín zdrojového toku ako prúd Zoznam. Metóda berie zdrojový prúd, veľkosť okna a preskočiť hodnotu ako parameter.

The Zoznam dĺžka sa rovná oknoveľkosť, zatiaľ čo shodnota kip určuje, kde podmnožina začína relatívne k predchádzajúcej podmnožine:

Celé číslo [] čísla = {1, 2, 3, 4, 5, 6, 7, 8}; Zoznam windowedWithSkip1 = StreamUtils .windowed (prúd (čísla), 3, 1) .collect (Collectors.toList ()); assertThat (windowedWithSkip1). obsahuje Presne (asList (1, 2, 3), asList (2, 3, 4), asList (3, 4, 5), asList (4, 5, 6), asList (5, 6, 7) )); 

Okrem toho je zaručené, že posledné okno bude mať požadovanú veľkosť, ako vidíme na nasledujúcom príklade:

Zoznam windowedWithSkip2 = StreamUtils.windowed (prúd (čísla), 3, 2) .collect (Collectors.toList ()); assertThat (windowedWithSkip2) .containsExactly (asList (1, 2, 3), asList (3, 4, 5), asList (5, 6, 7)); 

3.10. agregát ()

Existujú dva agregát () metódy, ktoré fungujú úplne inak.

Prvý agregát () zoskupuje prvky rovnakej hodnoty podľa daného predikátu:

Celé číslo [] čísla = {1, 2, 2, 3, 4, 4, 4, 5}; Zoznam agregovaný = StreamUtils .aggregate (Arrays.stream (numbers), (int1, int2) -> int1.compareTo (int2) == 0) .collect (Collectors.toList ()); assertThat (agregované). obsahuje Presne (asList (1), asList (2, 2), asList (3), asList (4, 4, 4), asList (5)); 

Predikát prijíma hodnoty súvislým spôsobom. Ak teda nie je objednané číslo, vyššie uvedené bude mať iný výsledok.

Na druhej strane druhá agregát () je jednoducho zvyknutý zoskupiť prvky zo zdrojového toku do skupín požadovanej veľkosti:

Zoznam aggregatedFixSize = StreamUtils .aggregate (stream (čísla), 5) .collect (Collectors.toList ()); assertThat (aggregatedFixSize) .containsExactly (asList (1, 2, 2, 3, 4), asList (4, 4, 5)); 

3.11. aggregateOnListCondition ()

aggregateOnListCondition () hodnoty skupín na základe predikátu a aktuálnej aktívnej skupiny. Predikát má momentálne aktívnu skupinu ako a Zoznam a ďalšia hodnota. Potom musí určiť, či má skupina pokračovať alebo má založiť novú skupinu.

Nasledujúci príklad rieši požiadavku na zoskupenie súvislých celočíselných hodnôt do skupiny, kde súčet hodnôt v každej skupine nesmie byť väčší ako 5:

Celé číslo [] čísla = {1, 1, 2, 3, 4, 4, 5}; Prúd aggregated = StreamUtils .aggregateOnListCondition (stream (numbers), (currentList, nextInt) -> currentList.stream (). mapToInt (Integer :: intValue) .sum () + nextInt <= 5); assertThat (agregované). obsahuje Presne (asList (1, 1, 2), asList (3), asList (4), asList (4), asList (5));

4. Streamovateľné

Prípad z Prúd nie je opakovane použiteľný. Pre tento dôvod, Streamovateľné poskytuje opakovane použiteľné streamy zabalením a odhalením rovnakých metód ako Prúd:

Streamable s = Streamable.of ("a", "b", "c", "d"); Zoznam zhromaždený1 = s.collect (Collectors.toList ()); Zoznam zhromaždený2 = s.collect (Collectors.toList ()); assertThat (zhromaždené1) .hasSize (4); assertThat (zhromaždené2) .hasSize (4);

5. CollectorUtils

CollectorUtils dopĺňa normu Zberatelia pridaním niekoľkých užitočných metód zberača.

5.1. maxBy () a minBy ()

maxBy ()vyhľadá maximálnu hodnotu v prúde pomocou dodanej projekčnej logiky:

Streamové kluby = Stream.of ("Juventus", "Barcelona", "PSG"); Voliteľné longestName = clubs.collect (CollectorUtils.maxBy (String :: length)); assertThat (longestName) .contains ("Barcelona");

Naproti tomu minBy ()nájde minimálnu hodnotu pomocou dodanej projekčnej logiky.

5.2. jedinečný ()

The jedinečný () zberateľ robí veľmi jednoduchú vec: vráti jedinú hodnotu, ak má daný stream presne 1 prvok:

Stream singleElement = Stream.of (1); Voliteľné unique = singleElement.collect (CollectorUtils.unique ()); tvrdiťTo (jedinečné) .obsahuje (1); 

Inak, jedinečný () vyvolá výnimku:

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

6. Záver

V tomto článku sme sa dozvedeli, ako knižnica Protonpack rozširuje rozhranie Java Stream API o jednoduchšie používanie. Pridáva užitočné metódy, ktoré by sme mohli bežne používať, ale v štandardnom API chýbajú.

Počnúc jazykom Java 9 budú niektoré zo funkcií poskytovaných Protonpackom k dispozícii v štandardnom Stream API.

Ako obvykle, kód nájdete na Githube.