Baseado nos cursos da Softblue
O que é a Stream API
- API que permite combinar operações
– Usada principalmente em coleções do Java
Introduzida no Java 8
Aproveita o uso de expressões lambda
Funciona bem para coleções pequenas e também para coleções muito grandes
– Usa a abordagem de lazy evaluation
- A Stream API permite encadear as operações (pipeline)
1
2
3
4
5
List<Integer> newList = list.stream()
.sorted()
.filter(e -> e >= 2 && e <= 8)
.map(e -> e * e)
.collect(Collectors.toList());
O tipo Stream
- As coleções List e Set possuem o método stream()
1
Stream<Integer> stream = list.stream();
O objeto Stream
é a porta de entrada para a Stream API O tipo parametrizado T depende do tipo da coleção
Para arrays, o código muda
1
2
int[] array = new int[10];
Stream<int[]> stream = Stream.of(array);
Operações
A Stream API possui uma série de operações para manipulação de dados
2 tipos
Intermediárias
Retornam um novo objeto Stream
Possibilitam o pipeline
Ex: sorted(), limit(), filter(), map()
Terminais
Geram um resultado final (redução)
Finalizam o uso da stream
Ex: collect(), reduce(), count(), max()
sorted()
Ordena os elementos da coleção
Permite fornecer ou não um Comparator
Operação intermediária
1
stream.sorted((e1, e2) -> e1.getNome().compareTo(e2.getNome())) //Expressão lambda que substitui uma instância de Comparator<T>
limit()
Define um tamanho máximo para a coleção
Os elementos que excedem o limite fornecido são removidos
Operação intermediária
1
Só os 10 primeiros elementos são mantidos
filter()
Filtra os resultados de acordo com um critério
Recebe um parâmetro Predicate
Operação intermediária
1
stream.filter(e -> e > 10);//Expressão lambda que determina a filtragem de elementos maiores que 10
distinct()
Remove elementos duplicados
Operação intermediária
1
stream.distinct();
map()
Mapeia um elemento em outro elemento (transformação)
Recebe um parâmetro Function<T, R>
Operação intermediária
1
stream.map(e -> e + 2);//Expressão lambda que incrementa 2 unidades a cada elemento
- Existem também mapeamentos especializados
– mapToInt() −> IntStream
– mapToDouble() −> DoubleStream
– mapToLong −> LongStream
collect()
Finaliza o pipeline, gerando um resultado
Operação terminal
A classe Collectors tem métodos estáticos que auxiliam nesta operação
Exemplos:
1
2
3
4
stream.collect(Collectors.toList())// List<T>
stream.collect(Collectors.toSet())// Set<T>
stream.collect(Collectors.counting())// Long
stream.collect(Collectors.summingInt(e -> e.getIdade()))// Integer
count()
Faz a contagem de elementos
Operação terminal
1
long c = stream.count();
Referenciando construtores
- Além de referenciar métodos, é possível também referenciar construtores
1
2
3
4
5
6
7
8
9
10
11
public class Pessoa {
private String nome;
public Pessoa(String nome) {
this.nome = nome;
}
}
List<String> nomes = Arrays.asList("José", "Maria", "Pedro");
List<Pessoa> pessoas = nomes.stream()
.map(Pessoa::new) //Equivale a: .map(e -> new Pessoa(e))
.collect(Collectors.toList());
Streams paralelas
- Uma stream paralela pode ser processada simultaneamente por vários núcleos de processamento
1
2
3
4
List<Integer> list = list.parallelStream()
.sorted()
.map(e -> e * e)
.collect(Collectors.toList());
- Para que o resultado seja consistente, as operações intermediárias precisam ser independentes