Cast from Optional<> to ArrayList<>

[亡魂溺海] 提交于 2020-07-18 11:40:46

问题


I have the following situation:

public ArrayList<A> getMethods(){
    return b.c.test();
}

So, my problem is that b.c.test() returns a value with Optional<A> as return type. But I need to return an ArrayList<A>.

So, I tried to cast it and rewrite it to :

public ArrayList<A> getMethods(){
    return (ArrayList<A>)b.c.test();
}

But Eclipse says that such a cast from Optional<A> to ArrayList<A> is not possible.

How can I solve this problem?


回答1:


I am presuming your intended semantic is 'if the value is present return a list with a single item, otherwise return an empty list.' In that case I would suggest something like the following:

ArrayList<A> result = new ArrayList<>();
b.c.test().ifPresent(result::add);
return result;

However I would suggest your return type should be List<A> rather than ArrayList<A> as that gives you the opportunity to change the type of list without changing the callers. It would also allow you to return Collections.EMPTY_LIST if the optional value is not present which is more efficient than creating an unnecessary ArrayList.

Update: there's now an easier option with Java 9:

b.c.test().stream().collect(Collectors.toList());



回答2:


In this case, it is possible to not use streams at all:

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

Or, the same code using the functional API:

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

I prefer the upper variant because I know for sure that it doesn't create any unnecessary objects on the Java heap.




回答3:


If everyone insists on using streams for this issue, it should be more idiomatic than using ifPresent() Unfortunately, Java 8 does not have a Optional.stream() method, so it is not possible to do:

 optional.stream().collect(Collectors.toList());

see also: Using Java 8's Optional with Stream::flatMap

But in JDK 9, it will be added (and that code actually already runs on Java 9)

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



回答4:


return b.c.test()
    .map(Arrays::asList).map(ArrayList::new)
    .orElseGet(ArrayList::new);

If the optional has a value, it "maps" it to a List<A> with Arrays.asList and then to an ArrayList via the new ArrayList<A>(List<A>) constructor; otherwise it yields an empty ArrayList via the empty constructor.

This could be more explicitly written out as:

return b.c.test()
    .map(value -> new ArrayList<A>(Arrays.asList(value)))
    .orElseGet(() -> new ArrayList<A>());



回答5:


With Java9, you can do this using the newly added Optional::stream API :

Optional<List<A>> list;
List<A> collect = list.stream()
               .flatMap(Optional::stream)
               .collect(Collectors.toList());



回答6:


If you're using Guava's Optional, you can do:

return new ArrayList<>(b.c.test().asSet());

This will extract the value from the Optional (if present) and add it to a new ArrayList.

If you're using Java 8, @sprinter's answer is what you need.




回答7:


An Optional is a container object which may or may not contain a non-null value.

In ArrayList terms I would translate it as an array which has 0 or 1 members.

public ArrayList<A> getMethods(){
  Optional<A> opt = b.c.test();
  ArrayList<A> res = new ArrayList<>();
  if ( opt.isPresent() )
    res.add( opt.get() );
  return res;
}


来源:https://stackoverflow.com/questions/31688382/cast-from-optional-to-arraylist

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!