Crearea unui flux de date
Pentru crearea unui flux de date pot fi utilizate diverse metode. Ca sursă a fluxului, putem folosi colecții. În special, în JDK 8, interfața Collection, care este implementată de toate clasele de colecții, a fost extinsă cu două metode pentru lucrul cu fluxurile:
- default Stream<E> stream: returnează un flux de date din colecție
- default Stream<E> parallelStream: returnează un flux paralel de date din colecție
Să analizăm un exemplu cu ArrayList:
import java.util.stream.Stream;
import java.util.*;
public class Program {
public static void main(String[] args) {
ArrayList<String> cities = new ArrayList<String>();
Collections.addAll(cities, "Paris", "Londra", "Madrid");
cities.stream() // obținem fluxul
.filter(s->s.length()==6) // aplicăm filtrarea după lungimea șirului
.forEach(s->System.out.println(s)); // afișăm șirurile filtrate la consolă
}
}
Aici, prin apelul cities.stream() obținem un flux care utilizează datele din lista cities. Prin fiecare operațiune intermediară aplicată fluxului, putem obține un flux modificat. De exemplu, putem modifica exemplul anterior astfel:
ArrayList<String> cities = new ArrayList<String>();
Collections.addAll(cities, "Paris", "Londra", "Madrid");
Stream<String> citiesStream = cities.stream(); // obținem fluxul
citiesStream = citiesStream.filter(s->s.length()==6); // aplicăm filtrarea după lungimea șirului
citiesStream.forEach(s->System.out.println(s)); // afișăm șirurile filtrate la consolă
Este important de menționat că, după utilizarea operațiunilor terminale, nu mai pot fi aplicate alte operațiuni terminale sau intermediare asupra aceluiași flux, deoarece fluxul a fost deja consumat. De exemplu, în cazul următor, vom obține o eroare:
citiesStream.forEach(s->System.out.println(s)); // operațiunea terminală consumă fluxul
long number = citiesStream.count(); // aici va apărea eroarea, deoarece fluxul a fost consumat
System.out.println(number);
citiesStream = citiesStream.filter(s->s.length()>5); // de asemenea nu este permis, deoarece fluxul a fost consumat
De fapt, ciclul de viață al unui flux parcurge următoarele trei etape:
- Crearea fluxului
- Aplicarea unei serii de operațiuni intermediare asupra fluxului
- Aplicarea unei operațiuni terminale și obținerea rezultatului
Pe lângă metodele discutate mai sus, mai există și alte modalități de creare a unui flux de date. Una dintre aceste modalități este metoda Arrays.stream(T[] array), care creează un flux de date dintr-un array:
Stream<String> citiesStream = Arrays.stream(new String[]{"Paris", "Londra", "Madrid"});
citiesStream.forEach(s->System.out.println(s)); // afișăm toate elementele array-ului
Pentru crearea fluxurilor IntStream, DoubleStream, LongStream, pot fi utilizate versiunile supraîncărcate ale acestei metode:
IntStream intStream = Arrays.stream(new int[]{1,2,4,5,7});
intStream.forEach(i->System.out.println(i));
LongStream longStream = Arrays.stream(new long[]{100,250,400,5843787,237});
longStream.forEach(l->System.out.println(l));
DoubleStream doubleStream = Arrays.stream(new double[] {3.4, 6.7, 9.5, 8.2345, 121});
doubleStream.forEach(d->System.out.println(d));
O altă modalitate de creare a unui flux este metoda statică of(T..values) din clasa Stream:
Stream<String> citiesStream = Stream.of("Paris", "Londra", "Madrid");
citiesStream.forEach(s->System.out.println(s));
// putem transmite un array
String[] cities = {"Paris", "Londra", "Madrid"};
Stream<String> citiesStream2 = Stream.of(cities);
IntStream intStream = IntStream.of(1,2,4,5,7);
intStream.forEach(i->System.out.println(i));
LongStream longStream = LongStream.of(100,250,400,5843787,237);
longStream.forEach(l->System.out.println(l));
DoubleStream doubleStream = DoubleStream.of(3.4, 6.7, 9.5, 8.2345, 121);
doubleStream.forEach(d->System.out.println(d));