Stream API
Java té una API que permet processar seqüències d'objectes mitjançant operacions que es poden afegir a una canonada. Un Stream
es genera a partir de col.leccions, arrays o canals d'E/S, i no és modificable: només podem canviar el resultat mitjançant les operacions de la canonada.
Tenim bàsicament dos tipus d'operacions: les intermèdies i les terminals.
- Operacions intermèdies: permeten afegir operacions addicionals al darrere.
- Operacions terminals: marquen el final del stream i retornen el resultat.
Les operacions s'encadenen en la canonada mitjançant crides successives que utilitzen expressions lambda. En el següent exemple, s'utilitza l'operació terminal forEach()
amb una expressió lambda de tipus Consumer.
List<Integer> list = Arrays.asList(3, 2, 5, 4, 1);
Stream<Integer> stream = list.stream();
Consumer<Integer> consumer = (number) -> { System.out.println(number); };
stream.forEach(consumer);
Operacions intermèdies:
-
map: permet aplicar una
Function
per a canviar el tipus delStream
de T a R<R> Stream<R> map(Function<? super T, ? extends R> mapper)
-
flatMap: permet aplicar una
Function
per a convertir cada T als continguts d'un stream de R<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
-
filter: permet modificar el stream filtrant els elements del
Stream
amb unPredicate
Stream<T> filter(Predicate<? super T> predicate)
-
sorted: permet ordenar els elements amb l'ordre natural (han de ser Comparable)
Stream<T> sorted()
Operacions terminals:
-
collect: permet reduir els elements amb un
Collector<T, A, R>
: T és l'entrada, A l'acumulació i R el tipus resultat. Tenim collectors a la classeCollectors
.<R,A> R collect(Collector<? super T,A,R> collector)
-
forEach: permet executar una acció per cada element.
void forEach(Consumer<? super T> action)
-
reduce: permet reduir els elements d'aquest stream utilitzant un
BinaryOperator
que permet ferT apply(T, T)
.Optional<T> reduce(BinaryOperator<T> accumulator)
Exemples:
// crear llista de sencers
List<Integer> number = Arrays.asList(2, 3, 4, 5);
// map
List<Integer> square = number.stream()
.map(x -> x * x)
.collect(Collectors.toList());
System.out.println(square);
// flatMap
List<Integer> square2 = number.stream()
.flatMap(x -> Stream.of(x, x*2))
.collect(Collectors.toList());
System.out.println(square2);
// crear llista de strings
List<String> names = Arrays.asList("Reflection", "Collection", "Stream");
// filter
List<String> result = names.stream()
.filter(s -> s.startsWith("S"))
.collect(Collectors.toList());
System.out.println(result);
// sorted
List<String> show = names.stream()
.sorted()
.collect(Collectors.toList());
System.out.println(show);
// crear llista de sencers
List<Integer> numbers = Arrays.asList(2, 3, 4, 5, 2);
// collect retorna un Set
Set<Integer> squareSet = numbers.stream()
.map(x -> x * x)
.collect(Collectors.toSet());
System.out.println(squareSet);
// forEach
number.stream()
.map(x -> x * x)
.forEach(y -> System.out.println(y));
// reduce
int even = number.stream()
.filter(x -> x % 2 == 0)
.reduce(0, (ans, i) -> ans + i);
System.out.println(even);