Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

220
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda