As vezes precisamos processar dados em um volume maior, onde é necessário filtrar a informação, selecionar ou alterar o que queremos para depois realizar o processamento. Como exemplo, vamos imaginar uma lista de alunos, onde cada instância tem seu nome e nota. Desta lista queremos a média geral, a média dos alunos aprovados (ou seja, quem tirou nota seis ou mais) e a média dos reprovados (nota menor que seis). Para isso, vamos primeiro visualizar nossa lista:
| |
Apesar da simplicidade dos nossos dados, para poder separar a nossa lista de forma a realizar esta média, precisamos iterar sobre todos os seus elementos. Vamos fazer primeiro a média mais simples, sem nenhum critério:
| |
Repare no trabalho de declarar a variável e iterar sobre todos os seus elementos, ainda de maneira simples, pois ainda não temos nenhuma regra implementada, vamos agora colocar os outros dois trechos de código, implementando a média dos aprovados e reprovados:
| |
Da mesma forma que meu modem toda vez que a internet cai, precisei reiniciar as variáveis de média e rescrever os for’s, mas eu sei que é possível fazer em apenas uma iteração, desta forma podemos economizar tempo, vamos tentar ver a versão reduzida deste código:
| |
Nesta versão, conseguimos reduzir bem o nosso código, centralizando tudo em um único foreach, porém o gerenciamento manual aumentou, pois tivemos que criar novas variáveis e ainda realizar o cálculo das médias dentro das chamadas das funções de saída.
Abstraindo a função do código, chegamos a algumas conclusões que podemos traduzir melhor, a primeira coisa que fazemos é filtrar com os requisitos que queremos, ou seja, as notas, depois de filtrar as entidades Aluno, devemos selecionar qual informação vamos processar (se necessário trata-la) e depois realizamos a agregação dessa informação, somando tudo em uma variável double (por exemplo, mediaAprovados).
No artigo passado, vimos como realizar a primeira tarefa utilizando o Java 8, onde aprendemos sobre os filtros, porém ainda precisamos realizar algumas outras operações, que é selecionar a informação que queremos (mapear) e depois agrega-la (reduzir). Para nossa sorte, a nova versão do Java também possui este tratamento, onde podemos trabalhar com métodos como map()(e suas variações) e reduce(), todas elas da classe Stream. Abaixo vemos o primeiro exemplo, da média geral:
| |
Chega a ser covarde a abordagem, todas as iterações estão encapsuladas e tudo é resolvido em apenas em uma linha, com uma sintaxe bem mais limpa, além de termos fornecidos métodos que realizam operações matemáticas, como average(), facilitando toda a operação. Agora vejamos como são todas as implementações, pegando a média dos aprovados e reprovados:
| |
Vemos que a legibilidade do código aumenta, mas repare que os três códigos são iguais, mudando apenas o filtro, e como repetição de código é mais feio que jogar cachorro na estrada, vamos pensar numa maneira mais bonita de lidar com o código. Lembre-se que as expressões lambda, como o nosso filtro, são na verdade implementações dinâmicas da classe Filter, então podemos receber ela como parâmetro. Vamos criar um método para lidar com esse parâmetro, recebendo a lista de alunos e o filtro, retornando a sua média:
| |
Agora que temos os métodos podemos substituir o código por chamadas as funções, mas lembre-se que não é necessário criar classes anônimas, afinal as expressões lambda são convertidas automaticamente pelamáquina virtual em implementações da interface:
| |
Repare como a nossa classe ficou muito mais simples, com um código simples de se compreender e dar manutenção, podendo ampliar facilmente a função. Fica muito simples processar informações desta forma, onde podemos não apenas selecionar as informações e reduzi-la, mas podemos transforma-la antes. Poderíamos converter para String’s todas as notas e concatena-las, ou mais mil e uma funções. Isso é inclusive a princípio de alguns banco de dados para processamento de grandes massas de dados, como o Hadoop, onde estas informações são utilizadas para análises de Business Inteligence e em sistemas de apoio a decisão.