Search code examples
javaguava

Guava: transform an List<Optional<T>> to List<T> keeping just present values


Is there an elegant way of using Guava to transform from a list of optionals to a list of present values?

For example, going from

ImmutableList.of(
    Optional.of("Tom"), Optional.<String>absent(), Optional.of("Dick"),
    Optional.of("Harry"), Optional.<String>absent()
)

to a list containing just

["Tom", "Dick", "Harry"]

One approach would be:

List<T> filterPresent(List<Optional<T>> inputs) {
    return FluentIterable.from(inputs)
            .filter(new Predicate<Optional<T>>() {
                @Override
                public boolean apply(Optional<T> optional) {
                    return optional.isPresent();
                }
            }).transform(new Function<Optional<T>, T>() {
                @Override
                public T apply(Optional<T> optional) {
                    return optional.get();
                }
            }).toList();
}

But this is verbose.

Java 8 is not an option, unfortunately.


Solution

  • There's actualy built-in method for this in Guava: presentInstances in Optional:

    Returns the value of each present instance from the supplied optionals, in order, skipping over occurrences of absent(). Iterators are unmodifiable and are evaluated lazily.

    Example:

    List<Optional<String>> optionalNames = ImmutableList.of(
        Optional.of("Tom"), Optional.<String>absent(), Optional.of("Dick"),
        Optional.of("Harry"), Optional.<String>absent());
    
    Iterable<String> presentNames = Optional.presentInstances(optionalNames); // lazy
    
    // copy to List if needed
    List<String> presentNamesList = ImmutableList.copyOf(presentNames);
    System.out.println(presentNamesList); // ["Tom", "Dick", "Harry"]