问题
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