Manipulando Lista com Java8 – Filtros, ordenações e conversões para outros tipos.
Olá, todos que trabalham com Java possuem algumas dificuldades ao trabalhar com listas (ou só eu?), certo? . Geralmente fazemos códigos gigantescos encadeando vários “ifs” e “elses” só para conseguir filtrar se fulano é pessoa física ou jurídica, sem falar quando desejamos também ordenar a mesma.
Além de ser um certo que trabalhoso, deixamos de ter também visibilidade de código. Veja o seguinte código:
for (Pessoa p: lista) { if (p.temCachorro() && p.estaVacinado()) { p.fazAlgumaCoisa("fazendo algo"); } }
A principio é algo bem simples, só que imagine esta mesma situação com muitos mais ifs e no final querendo filtrar está lista para outra, consegue imaginar o trabalho? Então eis que irei lhe apresentar uma nova forma de manipularmos isso com Java8.
Com a chegada do Java8, ganhamos diversos métodos para trabalharmos com lista, como: sorted, filter, foreach e etc. Para um primeiro exemplo, irei refatorar nosso código acima, veja:
lista.stream() .filter((Pessoa p) -> p.temCachorro && p.estaVacinado()) .forEach((Pessoa p) -> p.fazAlgumaCoisa("fazendo algo"));
Parece confuso? É, a primeira vista é sim, mas veja, não é mais simples de visualizar o que o código faz? Sabemos que na primeira parte estamos aplicando um filtro e na segunda estamos executando o método “fazAlgumaCoisa” para todos os objetos da lista. Bom, mas o que é esse tal de stream que estamos usando?
A grosso modo, o método stream() faz uma cópia da sua lista e tudo que for feita a partir do stream (você pode ler mais neste link), não irá alterar a lista “principal”, por exemplo: vamos criar uma lista de String simples, contendo algumas letras do alfabeto e depois vamos sortear nossa lista:
List<String> stringList = Arrays.asList("A","C","D","B"); stringList.stream() .sorted(Comparator.comparing(String::toString).forEach(System.out::println); // saída: A, B, C, D stringList.forEach(System.out::println); //saída: A, C, D, B
É importante lembrar que apesar do stream fazer um clone da sua lista, se você tiver uma lista de pessoa, e alterar o valor de um objeto a partir do stream, esse objeto será alterado nas “duas listas” devido ao fato de ambas terem o endereço de memória do mesmo objeto.
Bom, mas afinal, como que isso foi ordenado? Tanto o list quanto o stream, possuem um método chamado sorted (no caso da list, se chama sort), que esperar receber um comparetor como parâmetro dizendo o que desejamos alterar, no nosso caso, passamos a própria string que irá ser a regra da ordenação. Além disso, conseguimos também fazer ordenação de decrescente e com outras regras também, como:
List<String> stringList = Arrays.asList("A","C","D","B"); stringList.stream() .sorted(Comparator.comparing(String::toString) .thenComparing(String::length) .reversed()) .forEach(System.out::println);
Isso é muito mais simples que implementar a interface comparable e rescrever todos aqueles métodos para conseguirmos a ordenação que queremos.
E se quisermos pegar o primeiro resultado dessa lista, como fazemos? Simples, usamos o método findFirst que irá nos retornar o primeiro resultado da lista:
List<String> stringList = Arrays.asList("A","C","D","B"); stringList.stream() .sorted(Comparator.comparing(String::toString) .thenComparing(String::length) .reversed()) .findFirst().get();
E caso nossa lista não tenha nenhum objeto ou se caso tenha, esteja null, como tratamos isso? Mais simples ainda:
.findFirst().orElse("E");
No exemplo acima, caso o método findFirst não retorne nada ou retorne null, iremos receber como resultado o valor “E”. Útil, não?
E se quisermos transformar essa lista num map, como prosseguimos? Fácil, veja:
Map<String, Integer> result = stringList.stream().collect(Collectors.toMap(String::toString, String::length));
iremos ter um map com a chave como string e o valor sendo o tamanho dessa string.
Bom pessoal, isso foi só uma demonstração do que é possível fazer com uma lista usando java8. Existem muitos mais métodos que na medida do possível irei trazer para vocês.
Por hoje é isso, até mais e abraços.