Uvod u Java 8 Streams

1. Pregled

U ovom ćemo članku na brzinu pogledati jedan od glavnih dijelova nove funkcionalnosti koju je dodala Java 8 - Streamovi.

Objasnit ćemo o čemu se radi u streamovima i prikazati izradu i osnovne operacije prijenosa na jednostavnim primjerima.

2. Stream API

Jedna od glavnih novih značajki Java 8 je uvođenje stream funkcije - java.util.stream - koji sadrži klase za obradu sekvenci elemenata.

Središnja API klasa je Potok. Sljedeći će odjeljak pokazati kako se mogu stvoriti streamovi pomoću postojećih izvora davatelja podataka.

2.1. Stvaranje streama

Potoci se mogu stvarati iz različitih izvora elemenata, npr. zbirka ili niz uz pomoć stream () i od() metode:

String [] arr = new String [] {"a", "b", "c"}; Stream stream = Arrays.stream (arr); stream = Stream.of ("a", "b", "c");

A stream () zadana metoda dodana je u Kolekcija sučelje i omogućuje stvaranje a Stream koristeći bilo koju kolekciju kao izvor elemenata:

Stream stream = list.stream (); 

2.2. Višestruki navoj s streamovima

Stream API također pojednostavljuje multithreading pružanjem paralelni tok () metoda koja pokreće operacije nad elementima toka u paralelnom načinu.

Kôd u nastavku omogućuje pokretanje metode radi() paralelno za svaki element toka:

list.parallelStream (). forEach (element -> doWork (element));

U sljedećem odjeljku predstavit ćemo neke od osnovnih operacija Stream API-ja.

3. Stream operacije

Mnogo je korisnih operacija koje se mogu izvoditi u toku.

Dijele se na posredne operacije (povratak Stream) i terminalne operacije (vrati rezultat određenog tipa). Intermedijarne operacije omogućuju lančanstvo.

Također je vrijedno napomenuti da operacije na streamovima ne mijenjaju izvor.

Evo kratkog primjera:

dugo brojanje = popis.stream (). razlikovno (). brojanje ();

Dakle, različit () metoda predstavlja posrednu operaciju koja stvara novi tok jedinstvenih elemenata prethodnog toka. I računati() metoda je terminalna operacija, koji vraća veličinu toka.

3.1. Iteracija

Stream API pomaže zamjeni za, za svakoga, i dok petlje. Omogućuje koncentraciju na operacijsku logiku, ali ne i na iteraciju nad redoslijedom elemenata. Na primjer:

for (String string: list) {if (string.contains ("a")) {return true; }}

Ovaj se kod može promijeniti samo jednim retkom Java 8 koda:

boolean isExist = list.stream (). anyMatch (element -> element.contens ("a"));

3.2. Filtriranje

The filtar() metoda omogućuje nam odabir toka elemenata koji zadovoljavaju predikat.

Na primjer, uzmite u obzir sljedeći popis:

Popis ArrayList = novi ArrayList (); list.add ("Jedan"); list.add ("OneAndOnly"); list.add ("Derek"); list.add ("Promjena"); list.add ("tvornica"); list.add ("justBefore"); list.add ("Italija"); list.add ("Italija"); list.add ("četvrtak"); list.add (""); list.add ("");

Sljedeći kod stvara a Stream od Popis, pronalazi sve elemente ovog toka koji sadrže ukucati "d", i stvara novi tok koji sadrži samo filtrirane elemente:

Stream stream = list.stream (). Filter (element -> element.contens ("d"));

3.3. Mapiranje

Za pretvaranje elemenata a Stream primjenom posebne funkcije na njih i prikupljanja novih elemenata u Stream, možemo koristiti karta() metoda:

Popis uris = novi ArrayList (); uris.add ("C: \ My.txt"); Stream stream = uris.stream (). Map (uri -> Paths.get (uri));

Dakle, gornji kod pretvara Stream prema Stream primjenom određenog lambda izraza na svaki element početnog slova Stream.

Ako imate tok u kojem svaki element sadrži vlastiti slijed elemenata i želite stvoriti tok tih unutarnjih elemenata, trebali biste koristiti flatMap () metoda:

Popis detalja = novi ArrayList (); details.add (novi Detail ()); Stream stream = details.stream (). FlatMap (detail -> detail.getParts (). Stream ());

U ovom primjeru imamo popis elemenata tipa Detalj. The Detalj razred sadrži polje DIJELOVI, što je a Popis. Uz pomoć flatMap () metoda, svaki element iz polja DIJELOVI bit će izdvojeno i dodano novom rezultirajućem toku. Nakon toga početno Stream bit će izgubljeni.

3.4. Podudaranje

Stream API daje praktičan set instrumenata za provjeru valjanosti elemenata niza prema nekom predikatu. Da biste to učinili, može se koristiti jedna od sljedećih metoda: anyMatch (), allMatch (), noneMatch (). Njihova se imena sama po sebi objašnjavaju. To su terminalne operacije koje vraćaju a boolean:

boolean isValid = list.stream (). anyMatch (element -> element.contens ("h")); // istinito logičko isValidOne = list.stream (). allMatch (element -> element.contens ("h")); // lažno logičko isValidTwo = list.stream (). noneMatch (element -> element.contains ("h")); // lažno

Za prazne potoke, allMatch () vratit će se metoda s bilo kojim datim predikatom pravi:

Stream.empty (). AllMatch (Objects :: nonNull); // istina

Ovo je razumno zadano, jer ne možemo pronaći nijedan element koji ne zadovoljava predikat.

Slično tome, anyMatch () metoda se uvijek vraća lažno za prazne tokove:

Stream.empty (). AnyMatch (Objects :: nonNull); // lažno

Opet, ovo je razumno, jer ne možemo pronaći element koji zadovoljava ovaj uvjet.

3.5. Smanjenje

Stream API omogućuje smanjenje niza elemenata na neku vrijednost prema određenoj funkciji uz pomoć smanjiti() metoda tipa Stream. Ova metoda uzima dva parametra: prva - početna vrijednost, druga - funkcija akumulatora.

Zamislite da imate Popis i želite imati zbroj svih tih elemenata i neki početni znak Cijeli broj (u ovom primjeru 23). Dakle, možete pokrenuti sljedeći kod i rezultat će biti 26 (23 + 1 + 1 + 1).

Popis cijelih brojeva = Arrays.asList (1, 1, 1); Cijeli broj smanjen = cijeli brojevi.stream (). Smanjiti (23, (a, b) -> a + b);

3.6. Skupljanje

Smanjenje može pružiti i prikupiti() metoda tipa Potok. Ova je operacija vrlo zgodna u slučaju pretvaranja toka u Kolekcija ili a Karta i predstavlja tok u obliku jednog niza. Postoji klasa korisnosti Kolekcionari koji pružaju rješenje za gotovo sve tipične sakupljačke postupke. Za neke, ne trivijalne zadatke, običaj Kolektor može se stvoriti.

Popis rezultataList = list.stream (). Map (element -> element.toUpperCase ()). Collect (Collectors.toList ());

Ovaj kod koristi terminal prikupiti() operacija za smanjenje a Stream prema Popis.

4. Zaključci

U ovom smo se članku ukratko dotaknuli Java streamova - definitivno jedne od najzanimljivijih značajki Java 8.

Mnogo je naprednijih primjera upotrebe Streamova; Cilj ovog opisa bio je samo pružiti brz i praktičan uvod u ono što možete početi raditi s ovom funkcionalnošću i kao polazište za istraživanje i daljnje učenje.

Izvorni kod koji prati članak dostupan je na GitHubu.