番石榴:转换列表<optional <t>&gt;列出<t>保持现有值</t> </optional <t>

时间:2014-10-15 08:59:02

标签: java guava

是否有一种优雅的方式使用Guava从一个选项列表转换为一个现有值列表?

例如,从

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

到只包含

的列表
["Tom", "Dick", "Harry"]

一种方法是:

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();
}

但这很冗长。

不幸的是,Java 8不是一个选项。

4 个答案:

答案 0 :(得分:15)

在番石榴中有实际的内置方法:presentInstances in Optional

  

按顺序从提供的选项中返回每个当前实例的值,跳过absent()的出现次数。迭代器是不可修改的,并且被懒惰地评估。

示例:

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"]

答案 1 :(得分:5)

为什么不用老式的Java方式呢:

List<T> result = new ArrayList<T>();
for (Optional<T> optional : inputs) {
    if (optional.isPresent()) {
        result.add(optional.get());
    }
}
return result;

答案 2 :(得分:0)

您可以隐藏方法调用背后的谓词实例,以使代码更具可读性:

List<T> filterPresent(List<Optional<T>> inputs) {
    return FluentIterable.from(inputs).filter(present()).transform(value()).toList();
}

static <T> Predicate<Optional<T>> present() {
    return new Predicate<Optional<T>>() {
        @Override
        public boolean apply(Optional<T> optional) {
            return optional.isPresent();
        }
    };
}

static <T> Function<Optional<T>, T> value() {
    return new Function<Optional<T>, T>() {
        @Override
        public T apply(Optional<T> optional) {
            return optional.get();
        }
    };
}

不幸的是,在Java-8之前的生活中没有更简单的方法。

答案 3 :(得分:0)

如果要在循环中调用返回Optional的方法,并且要创建返回值的List,则可以使用toSet方法在Optional上与addAll上的List方法一起使用,如下所示:

List<String> strings = newArrayList();
for (Long id : ids) {
   strings.addAll(getString(id).toSet());
}

如果您想要返回List,而不是Iterable,则此选项非常有用。