пятница, 24 мая 2019 г.

Map value lazy initialization

Tired of the following pattern?


value = map.get(key);
if (value == null) {
    // Map value lazy initialization in act
    value = /* Init value */;
    map.put(key, value);
}
// Use value
Java2html


Here is the elegant solution from the Java 8:


import java.util.HashMap;
import java.util.Map;

public class MapInit {

  public static void main(String[] args) {
    Map<String, String> map = new HashMap<>();
    String ret;
    // Lambda function is called here as there is no value with "theKey" in the map
    // The same newly added value returned by the lambda function is returned 
    ret = map.computeIfAbsent("theKey", key -> "theValue");
    System.out.println(ret);
    System.out.println(map);
    // Lambda function isn't called here as there is the value with "theKey" in the map
    // Instead, the value with "theKey" is acquired from the map and returned
    ret = map.computeIfAbsent("theKey", key -> "theValue");
    System.out.println(ret);
    System.out.println(map);
    // The "mapping function" is called here as there is no value with "theInitiatedKey" in the map
    // The same newly allocated by the mapping function value is returned 
    ret = map.computeIfAbsent("theInitiatedKey", MapInit::valueInitiator);
    System.out.println(ret);
    System.out.println(map);
    // The "mapping function" isn't called here as there is the value with "theInitiatedKey" in the map
    // Instead, the value with "theInitiatedKey" is acquired from the map and returned
    ret = map.computeIfAbsent("theInitiatedKey", MapInit::valueInitiator);
    System.out.println(ret);
    System.out.println(map);
  }
  
  private static String valueInitiator(String key) {
    // The function is called if only the value with this key is absent from the map
    System.out.println("Initiating 'theInitiatedValue'");
    return "theInitiatedValue";
  }
}
Java2html

The output:

theValue
{theKey=theValue}
theValue
{theKey=theValue}
Initiating 'theInitiatedValue'
theInitiatedValue
{theKey=theValue, theInitiatedKey=theInitiatedValue}
theInitiatedValue
{theKey=theValue, theInitiatedKey=theInitiatedValue}


Inspired by the StackOverflow's question Java map.get(key) - automatically do put(key) and return if key doesn't exist?. Thanks for the solution to Roger Lindsjö.