I’ve lost count of the number of times I’ve seen code which fail-fast validates the state of something, using an approach like

public class PersonValidator {
  public boolean validate(Person person) {
    boolean valid = person != null;
    if (valid) valid = person.givenName != null;
    if (valid) valid = person.familyName != null;
    if (valid) valid = person.age != null;
    if (valid) valid = person.gender != null;
    // ...and many more
  }
}

It works, but it’s a brute force approach that’s filled with repetition due to the valid check. If your code style enforces braces for if statements (+1 for that), your method is also three times longer and growing every time a new check is added to the validator.

Using Java 8’s new stream API, we can improve this by taking the guard condition of if (valid) and making a generic validator that handles the plumbing for you.

import java.util.LinkedList;
import java.util.List;
import java.util.function.Predicate;
 
public class GenericValidator<T> implements Predicate {
 
  private final List<Predicate<T>> validators = new LinkedList<>();
 
  public GenericValidator(List<Predicate<T>> validators) {
    this.validators.addAll(validators);
  }

  @Override
  public boolean test(final T toValidate) {
    return validators.parallelStream()
                     .allMatch(predicate -> predicate.test(toValidate));
  }
} 

Using this, we can rewrite the Person validator to be a specification of the required validations (or even just create a static field of type GenericValidator).

public class PersonValidator extends GenericValidator<Person> {

  private static final List<Predicate<Person>> VALIDATORS = new LinkedList<>();

  static {
    VALIDATORS.add(person -> person.givenName != null);
    VALIDATORS.add(person -> person.familyName != null);
    VALIDATORS.add(person -> person.age != null);
    VALIDATORS.add(person -> person.gender != null);
    // ...and many more
  }

  public PersonValidator() {
    super(VALIDATORS);
  }
}

PersonValidator, and all your other validators, can now focus completely on validation. The behaviour hasn’t changed – the validation still fails fast. There’s no boiler plate, which is A Good Thing.

This one’s going in the toolbox.

UPDATE I saw a comment about this at when it was republished at JCG, and has been re-implemented with the suggestions there. There’s always something new to learn!

1 thought on “Fail-fast validations using Java 8 streams

  1. This is nice. Thanks a lot.

    But i have a question. How do we know which test is failed. In most of the cases we should know the reason for the validation failure. isn’t it?

Leave a Reply

Your email address will not be published. Required fields are marked *