Java map.get(key) - automatically do put(key) and return if key doesn't exist?

后端 未结 7 1161
你的背包
你的背包 2020-12-04 18:44

I am sick of the following pattern:

value = map.get(key);
if (value == null) {
    value = new Object();
    map.put(key, value);
}

This ex

相关标签:
7条回答
  • 2020-12-04 19:23

    The problem with this pattern is that you'd have to somehow define the value that should be used in case the get() returns null.

    There certainly are libraries out there and IIRC there are also some newer collections that do that, but unfortunately I don't remember which those were.

    However, you could write a utility method yourself, provided you have a standard way of creating the new values. Something like this might work:

    public static <K, V> V safeGet(K key, Map<K,V> map, Class<V> valueClass) throws /*add exceptions*/ {
      V value = map.get(key);
      if( value == null ) {
        value = valueClass.newInstance();
        map.put( key, value );
      }   
    
      return value;
    } 
    

    Note that you'd either have to throw the reflection exceptions or handle them in the method. Additionally, this requires the valueClass to provide a no-argument constructor. Alternatively, you could simply pass the default value that should be used.

    0 讨论(0)
  • 2020-12-04 19:31

    EDIT : Note that the feature mentioned below is long deprecated, and a CacheBuilder should be used instead.

    The Guava library has a "computing map", see MapMaker.makeComputingMap(Function).

    Map<String, Object> map = new MapMaker().makeComputingMap(
        new Function<String, Object>() {
          public String apply(Stringt) {
            return new Object();
          }
      });
    

    If you need the Function several times, extract it into a utility class, and then create the Map like this (where MyFunctions.NEW_OBJECT is the static Function instance):

    Map<String, Object> map = new MapMaker()
        .makeComputingMap(MyFunctions.NEW_OBJECT);
    
    0 讨论(0)
  • 2020-12-04 19:32

    Java 8 adds nice method to the Map: compute, computeIfPresent, computeIfAbsent

    To achieve what you need:

    Object existingOrCreated = map.computeIfAbsent(key, (k) -> new Object());
    
    0 讨论(0)
  • 2020-12-04 19:34

    You can use MutableMap and getIfAbsentPut() from Eclipse Collections which returns the value mapped to the key or inserts the given value and returns the given value if no value is mapped to the key.

    You can either use a method reference to create a new Object:

    MutableMap<String, Object> map = Maps.mutable.empty();
    Object value = map.getIfAbsentPut("key", Object::new);
    

    Or you can directly create a new Object:

    MutableMap<String, Object> map = Maps.mutable.empty();    
    Object value = map.getIfAbsentPut("key", new Object());
    

    In the first example, the object will be created only if there is no value mapped to the key.

    In the second example, the object will be created regardless.

    Note: I am a contributor to Eclipse Collections.

    0 讨论(0)
  • 2020-12-04 19:36

    The

    java.util.concurrent.ConcurrentMap 
    

    and from Java 8

    Java.util.Map
    

    has

    putIfAbsent(K key, V value) 
    

    which returns the value mapped to key or inserts the given value and null if no value is mapped for the key.

    If you need lazy evaluation of the value there is

    computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
    
    0 讨论(0)
  • 2020-12-04 19:39

    If in any case you need to get a default data in your map if it's not existing

    map.getOrDefault(key, defaultValue);
    

    javadocs

    0 讨论(0)
提交回复
热议问题