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.

Deixe um comentário

O seu endereço de e-mail não será publicado.