Java Optional - How to convert one type of list to another

Viewed 157

I have an optional Optional<TypeA> from which I can do a map function and get Optional<List<TypeB>>.

But I would like to now map it to Optional<List<TypeC>> and then orElse() it. So putting in pseudo code

Optional.ofNullable(fooReturnsTypeA()).map(TypeA::barReturnsListTypeB()).{?}.orElse(new ArrayList<TypeC>());

I know how to use map function, but it's been a while dealing with Optional with map. So, I might be just staring at the answer. Could someone help me with {?} part?

Regards,

3 Answers

What about this?

Optional.ofNullable(fooReturnsTypeA())
    .map(TypeA::barReturnsListTypeB())
    .map(typeBList->typeBList
        .stream()
        .map(TypeB::barReturnsTypeC)
        .collect(Collectors.toList())
    )
    .orElse(new ArrayList<TypeC>())

This basically creates a new Stream in .map and uses it to convert all elements of TypeB to TypeC (assuming TypeB has a method barReturnsTypeC without parameters that returns an instance of TypeC).

You can use another map and write method to convert List<TypeB> to List<TypeC>.

You're code will look like this:

    Optional.ofNullable(fooReturnsTypeA())
    .map(TypeA::barReturnsListTypeB())
    .map(this::convert)
    .orElse(new ArrayList<TypeC>());

And your method to convert:

    private List<TypeC> convert(List<TypeB> list) {
    // conversion logic
    // return List<TypeC>
}

First, I would replace the orElse with orElseGet. Depending on your code, using orElseGet instead of orElse can improve your performance. The parameter of orElse is evaluated even when the Optional is non-empty. On the other hand, the parameter of orElseGet is evaluated only when the Optional is empty. In your specific case, you may be instantiating unnecessary ArrayLists. From the Javadoc:

Supplier method passed as an argument is only executed when an Optional value is not present.

You can also dismiss the {?} by using a stream in the map.

Optional.ofNullable(fooReturnsTypeA())
    .map(typeA -> typeA.barReturnsListTypeB().stream()
            .map(TypeB::barReturnsTypeC).collect(Collectors.toList()))
    .orElseGet(() -> new ArrayList<TypeC>());

Note: see this for more information about the difference between orElse and orElseGet.

Related