Thirler
Thirler

Reputation: 20760

Map ifPresent function

How can I execute a function on a value of a map only if it is present, without making any changes to the map? I want to do this using the 'Java 8' declarative style, comparable to Optional.ifPresent().

My use case is as follows:

I receive updates (new or deleted) to objects in part, I want to register these updates with their parent. For bookkeeping I have the following:

Map<ParentId, Parent> parents = ...

When receiving a new child I do the following:

parents.computeIfAbsent(child.getParentId(), k -> new Parent()).addChild(child));

However for removing I can't find the declarative function. Straight forward I would implement this as:

if(parents.containsKey(child.getParentId())
{
     parents.get(child.getParentId()).removeChild(child);
}

Or I could wrap the value in an Optional:

Optional.ofNullable(parents.get(child.getParentId()).ifPresent(p -> p.removeChild(child));

Note that Parent is not a simple list, it contains more than just children. So the following doesn't work (because removeChild() doesn't return a Parent):

parents.computeIfPresent(child.getParentId(), (k, v) -> v.removeChild());

How can I do this, or is there no equivalent to Optional.ifPresent()?

Upvotes: 11

Views: 16094

Answers (2)

Andy Turner
Andy Turner

Reputation: 140484

If there are no side effects to creating an unnecessary parent, and no exception is thrown by removing an absent child, you could use:

parents.getOrDefault(child.getParentId(), new Parent()).removeChild(child);

Upvotes: 1

daniu
daniu

Reputation: 15008

I think your Optional solution looks ok, but for

the following doesn't work (because removeChild() doesn't return a Parent): parents.computeIfPresent(child.getParentId(), (k, v) -> v.removeChild());

you could extend the lambda to

parents.computeIfPresent(child.getParentId(), (k, v) -> { v.removeChild(); return v; });

I'd say the straight-forward way is clearest in this case though, I'd go with that.

Upvotes: 7

Related Questions