Uvod u Protonpack

1. Pregled

U ovom uputstvu razmotrit ćemo glavne značajke Protonpacka koji je knjižnica koja proširuje standard Stream API dodavanjem neke besplatne funkcionalnosti.

Pogledajte ovaj spis ovdje da biste otkrili osnove Java Stream API.

2. Ovisnost Mavena

Da bismo koristili knjižnicu Protonpack, moramo dodati ovisnost u našu pom.xml datoteka:

 com.codepoetics protonpack 1.15 

Potražite najnoviju verziju na Maven Central.

3. StreamUtils

Ovo je glavna klasa koja proširuje Javin standard Stream API.

Sve ovdje opisane metode su posredne operacije, što znači da mijenjaju a Stream ali ne pokreće njegovu obradu.

3.1. takeWhile () i takeUntil ()

takeWhile () uzima vrijednosti iz izvornog toka sve dok ispunjavaju isporučeni uvjet:

Stream streamOfInt = Stream .iterate (1, i -> i + 1); Rezultat popisa = StreamUtils .takeWhile (streamOfInt, i -> i <5) .collect (Collectors.toList ()); assertThat (result) .contens (1, 2, 3, 4);

Obrnuto, takeUntil () uzima vrijednosti dok vrijednost ne zadovolji isporučeni uvjet a zatim se zaustavlja:

Stream streamOfInt = Stream .iterate (1, i -> i + 1); Rezultat popisa = StreamUtils .takeUntil (streamOfInt, i -> i> = 5) .collect (Collectors.toList ()); assertThat (result) .containExactly (1, 2, 3, 4);

U Javi 9 nadalje, takeWhile () dio je standarda Stream API.

3.2. ZIP ()

ZIP () uzima dvije ili tri struje kao ulaz i funkciju kombinirača. Metoda uzima vrijednost iz istog položaja svake struje i prosljeđuje je kombiniraču.

To čini dok jedan od tokova ne ostane bez vrijednosti:

Gudački [] klubovi = {"Juventus", "Barcelona", "Liverpool", "PSG"}; String [] igrači = {"Ronaldo", "Messi", "Salah"}; Postavi zippedFrom2Sources = StreamUtils .zip (stream (klubovi), stream (igrači), (club, player) -> club + "" + player) .collect (Collectors.toSet ()); assertThat (zippedFrom2Sources) .sadrži ("Juventus Ronaldo", "Barcelona Messi", "Liverpool Salah"); 

Slično tome, preopterećen ZIP () koji traje tri izvora:

Niz [] lige = {"Serie A", "La Liga", "Premier League"}; Postavi zippedFrom3Sources = StreamUtils .zip (stream (klubovi), stream (igrači), stream (lige), (club, player, league) -> club + "" + player + "" + league) .collect (Collectors.toSet ( )); assertThat (zippedFrom3Sources) .sadrži ("Juventus Ronaldo Serie A", "Barcelona Messi La Liga", "Liverpool Salah Premier League");

3.3. zipWithIndex ()

zipWithIndex () uzima vrijednosti i zip svaku vrijednost sa svojim indeksom kako bi stvorio tok indeksiranih vrijednosti:

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

3.4. sjediniti()

sjediniti() radi s više izvora izvora i kombiniračem. To uzima vrijednost istog indeksnog položaja iz svakog izvora izvora i prosljeđuje ga kombiniraču.

Metoda djeluje uzimajući 1 vrijednost iz istog indeksa iz svakog slijeda uzastopno, počevši od sjeme vrijednost.

Zatim se vrijednost prosljeđuje kombiniraču, a rezultirajuća kombinirana vrijednost vraća se kombiniraču kako bi se stvorila sljedeća vrijednost:

Stream streamOfClubs = Stream .of ("Juventus", "Barcelona", "Liverpool", "PSG"); Stream streamOfPlayers = Stream .of ("Ronaldo", "Messi", "Salah"); Stream streamOfLeagues = Stream .of ("Serie A", "La Liga", "Premier League"); Postavi spojeno = StreamUtils.merge (() -> "", (valOne, valTwo) -> valOne + "" + valTwo, streamOfClubs, streamOfPlayers, streamOfLeagues) .collect (Collectors.toSet ()); assertThat (spojeno) .sadrži ("Juventus Ronaldo Serie A", "Barcelona Messi La Liga", "Liverpool Salah Premier League", "PSG");

3.5. mergeToList ()

mergeToList () uzima više tokova kao ulaz. To kombinira vrijednost istog indeksa iz svakog toka u Popis:

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

3.6. prošarati()

prošarati()stvara zamjenske vrijednosti preuzete iz više tokova pomoću a selektor.

Metoda daje skup koji sadrži po jednu vrijednost iz svakog toka u selektor, i selektor odabrat će jednu vrijednost.

Tada će se odabrana vrijednost ukloniti iz skupa i zamijeniti sljedećom vrijednošću iz koje je odabrana vrijednost potekla. Ta se ponavljanja nastavlja dok svi izvori ne ostanu bez vrijednosti.

Sljedeći primjer koristi prošarati() za stvaranje izmjeničnih vrijednosti s a kolobarnica strategija:

Stream streamOfClubs = Stream .of ("Juventus", "Barcelona", "Liverpool"); Stream streamOfPlayers = Stream .of ("Ronaldo", "Messi"); Stream streamOfLeagues = Stream .of ("Serija A", "La Liga"); Popis interleavedList = StreamUtils .interleave (Selectors.roundRobin (), streamOfClubs, streamOfPlayers, streamOfLeagues) .collect (Collectors.toList ()); assertThat (interleavedList) .hasSize (7) .containEase ("Juventus", "Ronaldo", "Serie A", "Barcelona", "Messi", "La Liga", "Liverpool"); 

Imajte na umu da je gornji kod za udžbenike jer je okrugli selektor pruža knjižnica kao Selektori.roundRobin ().

3.7. skipUntil () i preskočiDok ()

skipUntil () preskače vrijednosti dok vrijednost ne ispuni uvjet:

Cijeli broj [] brojevi = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; Popis preskočenUntilGreaterThan5 = StreamUtils .skipUntil (tok (brojevi), i -> i> 5) .collect (Collectors.toList ()); assertThat (preskočenUntilGreaterThan5) .containEaseally (6, 7, 8, 9, 10); 

U kontrastu, preskočiDok ()preskače vrijednosti dok vrijednosti ispunjavaju uvjet:

Cijeli broj [] brojevi = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; Popis preskočenWhileLessThanEquals5 = StreamUtils .skipWhile (stream (brojevi), i -> i <= 5 ||) .collect (Collectors.toList ()); assertThat (preskočenoWhileLessThanEquals5) .containsExactly (6, 7, 8, 9, 10); 

Jedna važna stvar oko preskočiDok () jest da će nastaviti s strujanjem nakon što pronađe prvu vrijednost koja ne ispunjava uvjet:

Popis preskočenWhileGreaterThan5 = StreamUtils .skipWhile (tok (brojevi), i -> i> 5) .collect (Collectors.toList ()); assertThat (skippedWhileGreaterThan5) .conlectEase (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 

U Javi 9 nadalje, ispustitiDok() u standardnom Stream API pruža istu funkcionalnost kao i preskočiDok ().

3.8. odvijati ()

odvijati () generira potencijalno beskonačan tok primjenom prilagođenog generatora na početnu vrijednost, a zatim na svaku generiranu vrijednost - tok se može prekinuti vraćanjem Neobvezno.prazno ():

Tok se odvijao = StreamUtils .unfold (2, i -> (i <100)? Neobvezno.od (i * i): Neobvezno.prazno ()); assertThat (unfolded.collect (Collectors.toList ())) .containsExactly (2, 4, 16, 256);

3.9. s prozorom ()

s prozorom ()stvara više podskupova izvornog toka kao tok Popis. Metoda uzima izvorni tok, veličina prozora i preskoči vrijednost kao parametar.

The Popis duljina jednaka prozorveličina, dok skip vrijednost određuje gdje podskup započinje u odnosu na prethodni podskup:

Cijeli broj [] brojevi = {1, 2, 3, 4, 5, 6, 7, 8}; Popis windowedWithSkip1 = StreamUtils .windowed (stream (brojevi), 3, 1) .collect (Collectors.toList ()); assertThat (windowedWithSkip1) .containEharely (asList (1, 2, 3), asList (2, 3, 4), asList (3, 4, 5), asList (4, 5, 6), asList (5, 6, 7 )); 

Uz to, posljednji prozor zajamčeno je željene veličine, kao što možemo vidjeti u sljedećem primjeru:

Popis windowedWithSkip2 = StreamUtils.windowed (stream (brojevi), 3, 2) .collect (Collectors.toList ()); assertThat (windowedWithSkip2) .containsEhactly (asList (1, 2, 3), asList (3, 4, 5), asList (5, 6, 7)); 

3.10. agregat ()

Postoje dva agregat () metode koje djeluju sasvim drugačije.

Prvi agregat () grupira elemente jednake vrijednosti prema danom predikatu:

Cijeli broj [] brojevi = {1, 2, 2, 3, 4, 4, 4, 5}; Zbirni popis = StreamUtils .aggregate (Nizovi.tok (brojevi), (int1, int2) -> int1.compareTo (int2) == 0) .collect (Collectors.toList ()); assertThat (agregirano). sadrži Tačno (asList (1), asList (2, 2), asList (3), asList (4, 4, 4), asList (5)); 

Predikat prima vrijednosti kontinuirano. Stoga će gore navedeno dati drugačiji rezultat ako broj nije naručen.

S druge strane, druga agregat () je jednostavno navikao na grupirajte elemente iz izvornog toka u skupine željene veličine:

Popis aggregatedFixSize = StreamUtils .aggregate (stream (brojevi), 5) .collect (Collectors.toList ()); assertThat (aggregatedFixSize) .conlectEhactly (asList (1, 2, 2, 3, 4), asList (4, 4, 5)); 

3.11. aggregateOnListCondition ()

aggregateOnListCondition () grupira vrijednosti na temelju predikata i trenutne aktivne grupe. Predikat ima trenutno aktivnu skupinu kao a Popis i sljedeća vrijednost. Tada mora utvrditi treba li grupa nastaviti ili pokrenuti novu grupu.

Sljedeći primjer rješava zahtjev za grupiranje susjednih cjelobrojnih vrijednosti u grupi, pri čemu zbroj vrijednosti u svakoj skupini ne smije biti veći od 5:

Cijeli broj [] brojevi = {1, 1, 2, 3, 4, 4, 5}; Stream agregirano = StreamUtils .aggregateOnListCondition (tok (brojevi), (currentList, nextInt) -> currentList.stream (). mapToInt (Integer :: intValue) .sum () + nextInt <= 5); assertThat (agregirano). sadrži Tačno (asList (1, 1, 2), asList (3), asList (4), asList (4), asList (5));

4. Streamable

Primjer Stream nije za višekratnu upotrebu. Zbog ovog razloga, Streamable pruža struje za ponovnu upotrebu omotavanjem i izlaganjem istih metoda kao i Stream:

Streamable s = Streamable.of ("a", "b", "c", "d"); Popis prikupljen1 = s.collect (Collectors.toList ()); Popis prikupljen2 = s.collect (Collectors.toList ()); assertThat (prikupljeno1) .hasSize (4); assertThat (prikupljeno2) .hasSize (4);

5. CollectorUtils

CollectorUtils nadopunjuje standard Kolekcionari dodavanjem nekoliko korisnih metoda sakupljača.

5.1. maxBy () i minBy ()

maxBy ()pronalazi maksimalnu vrijednost u toku koristeći isporučenu logiku projekcije:

Stream klubovi = Stream.of ("Juventus", "Barcelona", "PSG"); Neobvezno najduljeime = klubovi.zbir (CollectorUtils.maxBy (String :: length)); assertThat (najduljeName) .contens ("Barcelona");

U kontrastu, minBy ()pronalazi minimalnu vrijednost pomoću isporučene logike projekcije.

5.2. jedinstveno ()

The jedinstveno () kolekcionar radi vrlo jednostavnu stvar: vraća jedinu vrijednost ako zadani tok ima točno 1 element:

Stream singleElement = Stream.of (1); Po izboru unique = singleElement.collect (CollectorUtils.unique ()); assertThat (jedinstveni) .contens (1); 

Inače, jedinstveno () izbacit će iznimku:

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

6. Zaključak

U ovom smo članku saznali kako knjižnica Protonpack proširuje Java Stream API kako bi ga olakšala upotrebu. Dodaje korisne metode koje bismo mogli često koristiti, ali nedostaju u standardnom API-ju.

Počevši od Jave 9, neke funkcije koje pruža Protonpack bit će dostupne u standardnom Stream API-ju.

Kao i obično, kod se može naći na Githubu.


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