Is there a way to use method 'orElseGet' of 'Optional' to create a new list when it is null?

Robin Sun :

Say we have a class in the structure as below:

class Resource{
   String id; 
   String name;
   List<String> friends;
}

Is there a way to get the list using 'Optional' in this way:

Optional.of(resource.getFriends()).map(friends -> {
    friends.add("John");
    return friends;
}).orElseGet(
    //do something here.
)

A new list is expected if there was no one before.

Ole V.V. :

It depends on your more precise functional requirements. I present a couple of options.

If you just want a list that contains the friends of a resource and John:

    List<String> listWithJohn = Optional.ofNullable(resource.getFriends())
            .orElseGet(ArrayList::new);
    listWithJohn.add("John");

As Basil Bourque mentioned in a comment, since Java 9 the list initialization can instead be done using Objects.requireNonNullElseGet:

    List<String> listWithJohn
            = Objects.requireNonNullElseGet(resource.getFriends(), ArrayList::new);

If instead you want John added to the friends of the resource, I suggest that the getFriends method is where to edit:

/** @return The list of friends, not null */
public List<String> getFriends() {
    if (friends == null) {
        friends = new ArrayList<>();
    }
    return friends;
}

Returning the list itself makes resources vulnerable to callers modifying their friends lists unwantedly and unpredictably at any later time, though. Often one wishes to return a copy of the list or an unmodifiable view of it instead (preventing the caller from adding John as friend). In this case resources could have an addFriend method for adding friends.

EDIT:

is there a way to make in only one lambda code line?

    friends = friends == null ? new ArrayList<>() : friends;
    return friends;

But I would find it less readable (and there’s no lambda there, it’s just a one-liner). Or if you want it completely cryptic:

    return friends = friends == null ? new ArrayList<>() : friends;

Not recommended.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=105148&siteId=1