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

219
Visualizações
Stream API allMatch() with mulitple nullable nested objects

I'm working on a request validation feature where I need to check if a certain string value is present in a property that is contained in an object, which is contained as a value of a map entry, that map is a part of an object and finally my request body contains a set of those objects.

To try and make it clearer I will recreate my situation using only parts of code that are important.

Lets say my ClassA is received in request body, it has following properties:

@Nullable
Set<ClassB> mySet = null;

Now, we have ClassB that has a certain wrapper object of type ClassC:

@Nullable 
ClassC classC;

That wrapper class ClassC contains a map:

@Nullable
Map<String, ClassD> classDMap = new HashMap<>;

Finally, ClassD contains the property that needs to be checked if it contains a certain value:

@Nullable
String propertyForValidation;

At the moment I went with code that looks like this:

public boolean isValid(ClassA body) {
  return body.getMySet().stream()
                        .allMatch(x -> x.getClassC().getClassDMap().values().stream()
                        .allMatch(y -> y.getPropertyForValidation.equals("someValue"));
}

Current problem with my code is that it does not work as expected when some objects that I've described above are null since I'm getting a lot of NullPointerExceptions. I suppose this can be resolved with a lot ifs and null checks, but I was wondering if there is a more elegant way of doing it using Stream API?

All help is appreciated, thanks.

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

0

I'd try making use of Stream.filter(). Something like Stream.filter(x -> x!=null) should work instead of (and be more elegant than) if statements.

In your case it would be necessary before every one of your object or field (that is nullable) getters I'm afraid. But that's the most streamish' way I'd go for.

You can also use it in conjuction with the isEmpty() method for cases of empty maps.

An alternative would be to add if statements within your getter functions. That would allow you to keep the exact stream you wrote already.

over 4 years ago · Santiago Trujillo Relatório

0

Here is a solution using a single Stream. It is a bit repetitive but should comply with your expected results.

Note the usage of:

  • Objects#nonNull to check the nullity of an object using a method reference
  • The way the literal String is used first with equals to avoid the last NullPointerException possible

public boolean isValid(ClassA body) {
    return ofNullable(body.getMySet())
               .orElse(emptySet())
               .stream()
               .filter(Objects::nonNull)
               .map(ClassB::getClassC)
               .filter(Objects::nonNull)
               .map(ClassC::getClassDMap)
               .filter(Objects::nonNull)
               .flatMap(map -> map.values().stream())
               .allMatch(y -> "someValue".equals(y.getPropertyForValidation()));
}
over 4 years ago · Santiago Trujillo Relatório

0

Inspired by the comment of @Turing85, I tried to work this out with Optionals. I would not recommend this method but figured it could be educational to share here!

The effect of each orElse(Boolean.TRUE) is to return true when the respective component is missing/set is empty (if a missing component should fail validation, change this to Boolean.FALSE). If we can assume that no null values are ever set on the Map of ClassD, then Stream::allMatch can work directly on ClassD instead of Optional<ClassD>. Luckily, the final String::equals comparison provides one null check for free against the value returned by ClassD::getPropertyForValidation.

public boolean isValid(ClassA body) {
   return Optional.ofNullable(body)
           .flatMap(a -> Optional.ofNullable(a.getMySet()))
           .map(Set::stream)
           .map(streamB -> streamB
                   .map(b -> Optional.ofNullable(b.getClassC()))
                   .map(opC -> opC.flatMap(c -> Optional.ofNullable(c.getClassDMap())))
                   .map(opMapD -> opMapD
                           .map(map -> map.values().stream()
                                   .map(d -> Optional.ofNullable(d))
                                   .allMatch(opD -> opD
                                           .map(d -> "someValue".equals(d.getPropertyForValidation()))
                                           .orElse(Boolean.TRUE)))
                           .orElse(Boolean.TRUE))
                   .reduce((acc, item) -> acc && item)
                   .orElse(Boolean.TRUE))
           .orElse(Boolean.TRUE);
}
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