Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Mais de um filtro STREAM

Boa tarde pessoal,

Caso eu tenha um sistema de imoveis, onde eu cadastro, altero e filtro imoveis, como eu faria para combinar filtros utilizando o Stream?

Por exemplo: Eu quero filtrar um imovel no sistema atraves do bairro, quantidade de quartos e valor. Como fazer isso atraves do stream?

2 respostas

Fala aí Caio, blz?

Creio que dessa forma:

    List<Imovel> imoveis = ...

    List<Imovel> imoveisFiltrados = imoveis.stream()
    .filter( imovel -> {
        imovel.getBairro().equals("algum bairro") && 
        imovel.getQuantidadeDeQuartos() == 2 && 
        imovel.getValor() == 1000.00
    }).collect( Collectors.toList()) ;
solução!

Olá Caio, tudo bem ?

A ideia é que a partir da strem podemos usar o método filter passando - o que a própria API diz - um "predicado" (java.util.function.Predicate). Como toda interface funcional, Predicate tem apenas um método abstrato que precisamos implementar; o método test que recebe como parâmetro o elemento corrente que vem da Stream. Se esse elemento passar pelo teste - tiver este predicado - ele vai para a Stream resultante que é retornado ao final contendo os elementos filtrados.

Sendo assim, poderia ser algo do tipo:

Predicate<Imovel> filtroPersonalizado = new Predicate<Imovel>() {
    @Override
    public boolean test(Imovel imovel) {
        return imovel.getEndereco().getBairro().equals("Vila Mariana") &&
            imovel.getQtdQuartos() == 3 &&
            imovel.getValor().equals(new BigDecimal("500000"));
            // OBS: valores aqui foram fixos mesmo, use suas variaveis livremente
    }
};

List<Imovel> imoveisFiltrados = imoveis.stream()
        .filter(filtroPersonalizado).collect(Collectors.toList());
System.out.println(imoveisFiltrados);

Você pode implementar Predicate, instanciar um objeto de sua classe e utilizar uma de suas referências como parâmetro para o filter, ou mesmo usar uma classe anônima para definir a implementação, como no exemplo.

Se quiser seguir ainda mais o estilo funcional, pode inferir para essa implementação por meio de uma Lambda Expression. Algo como:

List<Imovel> imoveisFiltrados = imoveis.stream()
        .filter(imovel -> {
            return imovel.getEndereco().getBairro().equals("Tatuapé") &&
                imovel.getQtdQuartos() == 3 &&
                imovel.getValor().equals(new BigDecimal("500000"));
        }).collect(Collectors.toList());

System.out.println(imoveisFiltrados);

Pode ainda encadear filtros pra melhorar a semântica do seu código, caso a condição muito complexa incomode:

List<Imovel> imoveisFiltrados = imoveis.stream()
                .filter(imovel -> imovel.getEndereco().getBairro().equals("Tatuapé"))
                .filter(imovel -> imovel.getQtdQuartos() == 3)
                .filter(imovel -> imovel.getValor().equals(new BigDecimal("500000")))
                .collect(Collectors.toList());

        System.out.println(imoveisFiltrados);

De qualquer maneira e independente do aprendizado sobre a api do Java 8, vale lembrar, que tudo isso já pode ser feito ao carregar os dados na base de dados.

Espero ter ajudado. Abraço!