Cast from Optional<> to ArrayList<>

时间:2015-07-28 22:44:31

标签: java arraylist casting optional

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?

7 个答案:

答案 0 :(得分:18)

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

答案 1 :(得分:3)

If everyone insists on using streams for this issue, it should be more idiomatic than using func usernameIsTaken(username: String) -> Bool { //bool to see if username is taken var isTaken: Bool = false //access PFUsers var query : PFQuery = PFUser.query()! query.whereKey("User", equalTo: username) query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]?, error: NSError?) in if error == nil { if (objects!.count > 0){ isTaken = true println("username is taken") } else { println("Username is available. ") } } else { println("error") } } return isTaken } Unfortunately, Java 8 does not have a ifPresent() method, so it is not possible to do:

Optional.stream()

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.stream().collect(Collectors.toList());

答案 2 :(得分:3)

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

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

或者,使用功能API的相同代码:

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

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

答案 3 :(得分:2)

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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.

答案 6 :(得分:0)

使用Java9 ,您可以使用新添加的Optional::stream API执行此操作:

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