从Optional <>转换为ArrayList <>

use*_*712 5 java casting arraylist optional

我有以下情况:

public ArrayList<A> getMethods(){
    return b.c.test();
}
Run Code Online (Sandbox Code Playgroud)

所以,我的问题是b.c.test()返回一个Optional<A>返回类型的值.但我需要回归ArrayList<A>.

所以,我试图将其转换并重写为:

public ArrayList<A> getMethods(){
    return (ArrayList<A>)b.c.test();
}
Run Code Online (Sandbox Code Playgroud)

但是Eclipse说,从这样的投Optional<A>ArrayList<A>不可能的.

我怎么解决这个问题?

spr*_*ter 19

我假设您的预期语义是"如果值存在则返回包含单个项目的列表,否则返回空列表".在这种情况下,我建议如下:

ArrayList<A> result = new ArrayList<>();
b.c.test().ifPresent(result::add);
return result;
Run Code Online (Sandbox Code Playgroud)

但是我建议你的返回类型应该是,List<A>而不是ArrayList<A>让你有机会在不改变调用者的情况下改变列表类型.Collections.EMPTY_LIST如果不存在可选值,它还允许您返回,这比创建不必要的值更有效ArrayList.

更新:Java 9现在有了一个更简单的选项:

b.c.test().stream().collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)


小智 18

在这种情况下,可以根本不使用流:

public static <T> List<T> toList(Optional<T> opt) {
    return opt.isPresent()
            ? Collections.singletonList(opt.get())
            : Collections.emptyList();
}
Run Code Online (Sandbox Code Playgroud)

或者,使用函数式 API 的相同代码:

public static <T> List<T> toList(Optional<T> opt) {
    return opt
            .map(Collections::singletonList)
            .orElseGet(Collections::emptyList);
}
Run Code Online (Sandbox Code Playgroud)

我更喜欢上层变体,因为我确信它不会在 Java 堆上创建任何不必要的对象。


use*_*547 6

如果每个人都坚持使用流来解决这个问题,应该比使用更惯用ifPresent() 不幸的是,Java 8 没有Optional.stream()方法,因此无法做到:

 optional.stream().collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

另请参阅:将 Java 8 的 Optional 与 Stream::flatMap 一起使用

但是在 JDK 9 中,它将被添加(并且该代码实际上已经在 J​​ava 9 上运行)

Optional<Integer> o = Optional.empty();
final List<Integer> list = o.stream().collect(Collectors.toList());
System.out.println(list);
Run Code Online (Sandbox Code Playgroud)