Send from optional <> to ArrayList <>

I have the following situation:

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

      

So my problem is what is b.c.test()

returning value with Optional<A>

as return type. But I need to return ArrayList<A>

.

So, I tried to do this and rewrite it to:

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

      

But Eclipse says that such selection from Optional<A>

to ArrayList<A>

cannot be .

How can I solve this problem?

+3


source share


7 replies


I assume your intended semantics are "if value is present, return a list with one element, otherwise return an empty list". In this case, I would suggest the following:

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

      

However, I would suggest that your return type should be List<A>

, not ArrayList<A>

as it gives you the ability to change the type of the list without changing the callers. This will also allow you to return Collections.EMPTY_LIST

if the optional value is missing, which is more efficient than creating an unnecessary one ArrayList

.



Update : There is now a simpler option as of Java 9:

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

      

+11


source


If everyone insists on using streams for this problem, it should be more idiomatic than using ifPresent()

Unfortunately Java 8 does not have a method Optional.stream()

, so this cannot be done:

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

      

see also: Using Java 8 Options with Stream :: flatMap



But in JDK 9 it will be added (and this code already works in Java 9)

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

      

+2


source


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

      

If the parameter has a value, it "maps" it to List<A>

s Arrays.asList

and then ArrayList

to using the constructor new ArrayList<A>(List<A>)

; otherwise, an ArrayList

empty constructor is returned empty.

This could be more explicitly written as:

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

      

+1


source


Optional is a container object that may or may not contain a nonzero value.

In terms of ArrayList, I would translate it as an array that has 0 or 1 member.

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

      

0


source


If you are using Guava Optional

you can do:

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

      

This will extract the value from Optional

(if any) and add it to the new one ArrayList

.

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

0


source


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

      

0


source


In this case, you can 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 top option because I know for sure that it doesn't create unnecessary objects on the Java heap.

0


source







All Articles