Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

251
Visualizações
What is the best way of filtering by multiple fields in java

I have an entity with 10 fields:

Class Details{
  String item; 
  String name; 
  String type;
  String origin; 
  String color; 
  String quality;
  String country;
  String quantity;
  Boolean availability;
  String price;
 }

I have a restful endpoint that serves a List. I want the user to be able to provide search filters for each field. Currently I have QueryParam for each field. Then I filter by using java8 stream:

List<Detail> details;
details.stream().filter(detail-> detail.getItem()==item).filter(detail-> detail.getName()==name).....collect(Collectors.toList());

If I have 50 other classes with multiple fields that I want to filter, Is there a way of generalizing this?

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

You can compose such predicates with .and() and .or(), allowing you to define a single aggregate predicate that applies all the checks you would like, rather than trying to chain n .filter() calls. This enables arbitrarily complex predicates that can be constructed at runtime.

// Note that you shouldn't normally use == on objects
Predicate<Detail> itemPredicate = d-> item.equals(d.getItem());
Predicate<Detail> namePredicate = d-> name.equals(d.getName());

details.stream()
    .filter(itemPredicate.and(namePredicate))
    .collect(Collectors.toList());
over 4 years ago · Santiago Trujillo Relatório

0

If you want to avoid reflection how about something like this?

static enum DetailQueryParams {

    ITEM("item", d -> d.item),
    NAME("name", d -> d.name),
    TYPE("type", d -> d.type),
    ORIGIN("origin", d -> d.origin),
    COLOR("color", d -> d.color),
    QUALITY("quality", d -> d.quality),
    COUNTRY("country", d -> d.country),
    QUANTITY("quantity", d -> d.quantity),
    AVAILABILITY("availability", d -> d.availability),
    PRICE("price", d -> d.price);

    private String name;
    private Function<Detail, Object> valueExtractor;

    private DetailQueryParams(String name, 
            Function<Detail, Object> valueExtractor) {
        this.name = name;
        this.valueExtractor = valueExtractor;
    }

    public static Predicate<Detail> mustMatchDetailValues(
            Function<String, Optional<String>> queryParamGetter) {
        return Arrays.asList(values()).stream()
                .map(p -> queryParamGetter.apply(p.name)
                        .map(q -> (Predicate<Detail>) 
                                d -> String.valueOf(p.valueExtractor.apply(d)).equals(q))
                        .orElse(d -> true))
                .reduce(Predicate::and)
                .orElse(d -> true);
    }

}

And then, assuming that you can access query params by e.g. request.getQueryParam(String name) which returns a String value or null, use the code by calling the following:

details.stream()
    .filter(DetailQueryParams.mustMatchDetailValues(
            name -> Optional.ofNullable(request.getQueryParam(name))))
    .collect(Collectors.toList());

What the method basically does is:

- for each possible query param
    - get its value from the request
    - if value is present build predicate which
        - gets field value from detail object and convert to string
        - check that both strings (queried and extracted) matches
    - if value is not present return predicate that always returns true
- combine resulting predicates using and
- use always true as fallback (which here never actually happens)

Of course this could also be extended to generate predicates depending on the actual value type instead of comparing strings so that e.g. ranges could be requested and handled via "priceMin" and/or "priceMax".

over 4 years ago · Santiago Trujillo Relatório

0

For Lambda details -> condition. So we can specify how many required.

details.stream().filter(detail-> detail.getItem()==item && detail.getName()==name && ...)
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda