Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using optional to populate value in a Map

Tags:

java

I am new to Java, and still learning Optionals. I understood its used to avoid Null Pointer Exception.

I have a piece of code wherein I want to use optional, which is like this:

    final MetadataExtractor<FCAddress> metadataExtractor = t -> {
        final Map<String, String> metadata = new HashMap<>();
        metadata.put("senderCountryCode", t.getCountryCode());
        metadata.put("senderState", t.getState());
        metadata.put("senderPostalCode",t.getPostalCode());
        return metadata;
    };

Here, my use case is, if the SenderState is empty, i.e. t.getState() is empty, I want the map field to to be empty, that is not populated.

I tried something like this:

    final MetadataExtractor<FCAddress> metadataExtractor = t -> {
        final Map<String, String> metadata = new HashMap<>();
        metadata.put("senderCountryCode", t.getCountryCode());
        Optional<String> senderState = Optional.of(t.getState());
        senderState.ifPresent(metadata.put("senderState", t.getState());
        metadata.put("senderPostalCode",t.getPostalCode());
        return metadata;
    };

But this gives a compilation error, where am I going wrong in this? Error is: "ifPresent (java.util.function.Consumer) in Optional cannot be applied"

like image 821
user3797829 Avatar asked May 14 '26 16:05

user3797829


2 Answers

You need to pass a Consumer (a lambda) to ifPresent:

senderState.ifPresent(state -> metadata.put("state", state);
// important: the Consumer always receive a parameter.
// An empty value `() ->` is not valid!

The lambda will only get executed in case senderState is present (that means, is not null).

BTW it's very important to construct your senderState by using Optional.ofNullable(...)! Otherwise, it'll throw an NPE.

Check out an in-depth tutorial: https://www.baeldung.com/java-optional

like image 148
Pavel Kalmykov Razgovorov Avatar answered May 17 '26 05:05

Pavel Kalmykov Razgovorov


In this particular code the use of Optional is not useful because you don't like to add an Optional to the map, but only skip null values.

The simplest solution that doesn't create new objects is adding a check on value of t.getState() as follow:

final MetadataExtractor<FCAddress> metadataExtractor = t -> {
    final Map<String, String> metadata = new HashMap<>();
    metadata.put("senderCountryCode", t.getCountryCode());
    if (t.getState() != null) {
       metadata.put("senderState", t.getState());
    }
    metadata.put("senderPostalCode",t.getPostalCode());
    return metadata;
};

Just for studying purpose the solution of GhostCat works with an Optional:

senderState.ifPresent(() -> metadata.put("senderState", t.getState());

the complete example will be:

final MetadataExtractor<FCAddress> metadataExtractor = t -> {
    final Map<String, String> metadata = new HashMap<>();
    metadata.put("senderCountryCode", t.getCountryCode());

    // Here you create a not useful object that can be replaced with a simple if
    Optional<String> senderState = Optional.ofNullable(t.getState());

    // Here you create a second not necessary object because a lambda
    // espression is an instance of an anonimous class implementing
    // the corresponding interface
    senderState.ifPresent(() -> 
         metadata.put("senderState", t.getState()
    );
    metadata.put("senderPostalCode",t.getPostalCode());
    return metadata;
};

Note that this solution will create two unnecessary objects:

  • The explicit Optional senderState
  • and another object for the Consumer created as lambda expression inside the ifPresent method
like image 21
Davide Lorenzo MARINO Avatar answered May 17 '26 05:05

Davide Lorenzo MARINO



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!