Jordi
Jordi

Reputation: 23277

java streams: elegant way to filter according an exception is thrown

Is there any more elegant way to filter according if an exception is thrown?

I mean, currently my code looks like:

stream.filter(item -> {
    try {
        validator.with(reference)
            .hasAccess(this.authzManager)
            .isOwner();
        } catch (EspaiDocFault | DataAccessException e) {
            return false;
        }
        return true;
    }
)

What I'm trying to do is if an exception is thrown current item stream has to be filtered.

I'm looking for any existing util class or something similar...

Upvotes: 3

Views: 421

Answers (2)

Andrew
Andrew

Reputation: 49656

A very common approach I've seen in many variations is to write own functional interface that will allow a checked exception to be thrown (1) and to adapt that solution to a built-in interface (2).

/**
 * An EPredicate is a Predicate that allows a checked exception to be thrown.
 *
 * @param <T> the type of the input to the predicate
 * @param <E> the allowed exception
 */
@FunctionalInterface
public interface EPredicate<T, E extends Exception> {

    /**
     * (1) the method permits a checked exception
     */
    boolean test(T t) throws E;

    /**
     * (2) the method adapts an EPredicate to a Predicate.
     */
    static <T, E extends Exception> Predicate<T> unwrap(EPredicate<T, E> predicate) {
        return t -> {
            try {
                return predicate.test(t);
            } catch (Exception e) {
                return false;
            }
        };
    }

}

An example looks quite elegant:

.stream()
.filter(EPredicate.<ItemType, Exception>unwrap(item -> validator.[...].isOwner()))

where,

  • ItemType is the type of item;
  • Exception is a common parent of EspaiDocFault and DataAccessException.

.stream()
.filter(EPredicate.unwrap(item -> validator.[...].isOwner()))

Upvotes: 2

Druckles
Druckles

Reputation: 3792

The Vavr library has a Try class that can do what you want:

stream.filter(item -> Try.of(() -> validator.with(reference)
                .hasAccess(this.authzManager)
                .isOwner()).getOrElse(false))

Edit: if you actually want to know whether the exception was thrown or not, Vavr can do that too:

stream.filter(item -> Try.of([...]).isSuccess())

Alternatively, wrap the whole thing in a method:

stream.filter(this::getMyBooleanWithinMyTry)

Upvotes: 2

Related Questions