Streamy primitívneho typu v prostredí Java 8
1. Úvod
Stream API bol jednou z kľúčových funkcií pridaných do Java 8.
Stručne povedané, API nám umožňuje pohodlne a efektívnejšie spracovávať zbierky a ďalšie sekvencie prvkov poskytovaním deklaratívneho API.
2. Primitívne toky
Streamy primárne pracujú so zbierkami objektov, nie s primitívnymi typmi.
Našťastie poskytnúť spôsob práce s tromi najpoužívanejšími primitívnymi typmi - int, dlho a dvojitý - štandardná knižnica obsahuje tri primitívne špecializované implementácie: IntStream, LongStream, a DoubleStream.
Primitívne streamy sú obmedzené hlavne kvôli réžii boxu a vytváraniu špecializovaných streamov pre iné primitívy nie je v mnohých prípadoch také užitočné.
3. Aritmetické operácie
Začnime niekoľkými zaujímavými metódami pre veľmi používané aritmetické operácie, ako sú napr min, max, súčeta priemer:
int [] cele cisla = new int [] {20, 98, 12, 7, 35}; int min = Arrays.stream (celé čísla) .min () .getAsInt (); // vráti 7
Poďme si teraz prejsť fragment kódu vyššie, aby sme pochopili, o čo ide.
Vytvorili sme naše IntStream používaním java.util.Arrays.stream (int []) a potom použil min () metóda na získanie najnižšieho celého čísla ako java.util.OptionalInt a nakoniec zavolal getAsInt () získať int hodnotu.
Ďalším spôsobom, ako vytvoriť IntStream používa IntStream.of (int…). The max () metóda vráti najväčšie celé číslo:
int max = IntStream.of (20, 98, 12, 7, 35) .max () .getAsInt (); // vráti 98
Ďalej - aby sme dostali súčet celých čísel, ktoré práve nazývame suma () metóda a nemusíme používať getAsInt () pretože už vráti výsledok ako int hodnota:
int sum = IntStream.of (20, 98, 12, 7, 35). sum (); // vráti 172
Vyvolávame priemer () metóda na získanie priemeru celočíselných hodnôt a ako vidíme, mali by sme ju použiť getAsDouble () pretože vracia hodnotu typu dvojitý.
double avg = IntStream.of (20, 98, 12, 7, 35) .average () .getAsDouble (); // vráti 34.4
4. Rozsah
Môžeme tiež vytvoriť IntStream na základe rozsahu:
int sum = IntStream.range (1, 10) .sum (); // vráti 45 int sum = IntStream.rangeClosed (1, 10) .sum (); // vráti 55
Ako ukazuje útržok kódu vyššie, existujú dva spôsoby, ako vytvoriť rozsah celočíselných hodnôt rozsah () a rangeClosed ().
Rozdiel je v tom, že koniec rozsah () je exkluzívny, zatiaľ čo je zahrnutý v rangeClosed ().
Metódy rozsahu sú k dispozícii iba pre IntStream a LongStream.
Range môžeme použiť ako efektnú formu slučky for-each:
IntStream.rangeClosed (1, 5) .forEach (System.out :: println);
Čo je dobré pri ich použití ako náhrady slučky for-each je, že môžeme tiež využiť výhody paralelného vykonávania:
IntStream.rangeClosed (1, 5) .parallel () .forEach (System.out :: println);
Aj keď sú tieto efektné slučky užitočné, je stále lepšie použiť tradičné slučky for-loop namiesto funkčných na jednoduché iterácie, pretože v niektorých prípadoch sú jednoduché, čitateľné a výkonné.
5. Box a Unboxing
Sú chvíle, kedy potrebujeme previesť primitívne hodnoty na ich obalové ekvivalenty.
V týchto prípadoch môžeme použiť škatuľka () metóda:
Zoznam evenInts = IntStream.rangeClosed (1, 10) .filter (i -> i% 2 == 0) .boxed () .collect (Collectors.toList ());
Môžeme tiež konvertovať z prúdu triedy wrapper na primitívny prúd:
// vráti 78 int sum = Arrays.asList (33,45) .stream () .mapToInt (i -> i) .sum ();
Vždy môžeme použiť mapToXxx a flatMapToXxx metódy na vytváranie primitívnych prúdov.
6. Záver
Java Streams je veľmi silný doplnok k jazyku. Sotva sme tu poškriabali povrch primitívnych prúdov, ale ako už môžete použiť na svoju produktivitu.
A ako vždy, vzorky kódu nájdete na GitHub.