Voltar
Por que eu devo ler este artigo:

Este artigo apresenta a Streams API, uma das novidades do Java 8 que traz facilidades e melhorias para o processamento de elementos em coleções. Com o uso da Streams API, as operações passam a ser pensadas sobre “o que fazer”, ao invés do “como fazer”. Essa abordagem é possível devido a abstrações que encapsulam operações comuns realizadas sobre coleções.

Assim como a API Collections, amplamente adotada hoje em dia e que faz parte do cotidiano dos desenvolvedores Java, muito em breve a Streams API atingirá este nível de adoção por causa das suas características complementares à API Collections, fazendo com que o aprendizado e o domínio dessa nova API sejam essenciais.

A Streams API é uma das grandes novidades do Java 8. Diretamente relacionada com a API Collections, fornece suporte a uma série de operações sobre coleções de dados e, conforme o avanço da adoção da plataforma Java 8, muito em breve seu uso estará bastante difundido entre desenvolvedores, da mesma forma que a API Collections.

Como sabemos, o número de aplicações Java que fazem uso de recursos da API Collections é bastante elevado, pois coleções são fundamentais em muitas tarefas de processamento de dados. Um exemplo de tarefa comum envolvendo Collections é a criação de coleções de dados e seu posterior processamento como, por exemplo, uma coleção de ordens de venda em um sistema de comércio eletrônico e o processamento dessas ordens para obter o valor total das vendas. Para realizar esse processamento, seria necessário percorrer toda a coleção em um laço e, com a ajuda de uma variável temporária, somar cada valor para obter o total.

Assim, podemos concluir que a tarefa de percorrer e realizar uma operação em cada elemento de uma coleção é um padrão de processamento. Em um banco de dados relacional, por outro lado, para obter o valor total das ordens de venda seria necessário algo como SELECT SUM(orders.total) FROM orders. Note que não é necessário percorrer todos os registros e muito menos implementar como calcular o valor total, pois tudo é feito de forma declarativa em termos do que se é esperado. Agora, como fazer isso com Collections e poupar bastante trabalho, eliminando a implementação de laços para processamento de coleções? Este é um dos problemas que a Streams API, da plataforma Java 8, vem resolver.

Outra questão ao lidar com o processamento de coleções está relacionada à eficiência do processamento. Para melhorar a performance do processamento o ideal seria o uso de paralelismo, embora código paralelo seja mais difícil de escrever e sujeito a erros. Pensando nisso, a Streams API também traz recursos para lidar com essa questão. Ao fornecer uma abstração que permite o processamento de coleções de forma declarativa, além de possibilitar que o processamento seja realizado de forma paralela sem a necessidade de código adicional, Streams API muda o jeito como coleções de dados são processadas.

Como motivação para o aprendizado e para ter uma ideia de como a Streams API funciona, considere a Listagem 1, que mostra como obter o valor total das ordens de compra em uma determinada lista. O cálculo é feito por meio de um laço que itera por todos os elementos da lista, o valor de cada ordem é recuperado e somado em uma variável temporária. Quando toda a lista é iterada, tem-se o valor total das ordens de compra da lista.


public double getOrdersTotal(List<Order> orders) {
               
  double ordersTotal = 0.0;
         
  for(Order order : orders) {
   ordersTotal = ordersTotal + order.getTotal();
  }
   
  return ordersTotal;
}
Listagem 1. Método corriqueiro para percorrer uma lista e obter o valor total

Agora considere a Listagem 2, que obtém o mesmo resultado, entretanto, fazendo uso da Streams API. Note como as coisas ficaram bem mais simples e o código muito mais natural para se ler. Neste momento, não se preocupe em entender todo o código dessa listagem. O objetivo agora é mostrar o quão conciso se torna o código com a Streams API. Os detalhes do que essa linha de código faz serão abordados adiante.


Double ordersTotal = orders.stream().mapToDouble((order) -> order.getValue()).sum();
Listagem 2. Código utilizando a Streams API para percorrer uma lista e obter o valor total

As próximas seções deste artigo apresentam todos os detalhes da Streams API, começando de forma conceitual mostrando o que é uma stream, até a prática de como criar streams e realizar operações sobre as mesmas.

Streams

Para a Streams API, uma Stream pode ser definida, de forma sucinta, como uma sequência de elementos de uma fonte de dados que suporta operações de agregação. A abordagem de trabalho da Streams API é a conversão de uma >coleção, array ou recursos I/O (entrada e saída de dados) em uma Stream, o processamento dos dados e a devolução dos dados em uma nova coleção ou valor reduzido (map-reduce).

Uma Stream fornece uma interface para acesso sequencial aos elementos da mesma, que são de determinado tipo. Streams podem ser criadas a partir de coleções, arrays e I/O, mas não armazenam os elementos, que são processados sob demanda, com operações parecidas com as funções da SQL e operações comuns em linguagens de programação funcional, como filter(), map(), reduce(), find( ...

Quer ler esse conteúdo completo? Tenha acesso completo