2011-01-28 80 views
32

我在我的代碼中有一個Map<String, List<String>>,如果映射的#get()方法返回一個空列表而不是null,那麼我會避免潛在的空指針。在java API中有這樣的事情嗎?我應該只是延長HashMapJava Map實現返回一個默認值而不是null

+7

使用Decorator模式很可能比HashMap中延伸......好我 – kem 2011-01-28 21:50:56

+1

不懷疑你,但爲什麼會更好? – 2011-01-28 21:52:55

+7

@jk:你爲什麼要限制自己*總是*作爲一個HashMap?如果有時你想要一個LinkedHashMap?還是一個ConcurrentHashMap?還是一個TreeMap?基本上,贊成組合比繼承:) – 2011-01-28 21:54:05

回答

23

@ Jon的回答是一種很好的方式來做你直接要求的東西。

但是,讓我感到你可能試圖實現的是一個「multimap」;即從一個鍵到一組值的映射。如果是這種情況,那麼你還應該看看Guava或Apache commons集合中的multimap類。

看:

24

正如評論指出:

番石榴的計算映射的概念與LoadingCache取代。另外java 8引入了Map接口,不錯的computeIfAbsent默認方法,不破解地圖合同和功能懶惰評估。


Guava有一個「計算圖」將執行的功能,以提供一個值,如果它是不存在的想法。它在MapMaker.makeComputingMap執行;您現在可以使用CacheBuilder - 有關更多詳細信息,請參見CacheBuilder.build

這可能是矯枉過正你以後 - 你可能會更好只是寫一個Map實現其一個Map(使用成分而不是擴展任何特定的實現),然後就返回默認值,如果它不是當下。比get其他每個方法很可能只是委託給其他地圖:

public class DefaultingMap<K, V> implements Map<K, V> 
{ 
    private final Map<K, V> map; 
    private final V defaultValue; 

    public DefaultingMap(Map<K, V> map, V defaultValue) 
    { 
     this.map = map; 
     this.defaultValue = defaultValue; 
    } 

    @Override public V get(Object key) 
    { 
     V ret = map.get(key); 
     if (ret == null) 
     { 
      ret = defaultValue; 
     } 
     return ret; 
    } 

    @Override public int size() 
    { 
     return map.size(); 
    } 

    // etc 
} 
0

在我看來,你可以簡單地編寫一個包裝函數來獲得你想要的值,如果它是null返回默認代替。

Map<String, List<String>> myMap = new Map<String, List<String>>(); 

public List<String> myGet(String key) { 
    List<String> ret = myMap.get(key); 
    if(ret == NULL) { 
     return defaultList(); // where defaultList is a function that generates your default list. 
    } 
    return ret; 
} 

這是假設你的myMap是一個全局變量(爲簡單起見),如果這不是你想要的那麼你還可以擴展MapHashMap成類似MyMap,只是包括這個額外的功能。這樣你就可以在任何一個MyMap對象被實例化的地方使用它。

8

與以前的帖子類似,除非您可以重寫get方法,如果您要更改其行爲。

Map<String, List<String>> map = new LinkedHashMap<String, List<String>>() { 
    public String get(Object key) { 
     List<String> list = super.get(key); 
     if (list == null && key instanceof String) 
      super.put(key, list = new ArrayList<String>()); 
     return list; 
    } 
}; 
7

番石榴有一個方法來做你想要的。它與Argote's answer類似。

Map<String, List<String>> myMap = ... 
Functions.forMap(myMap, Arrays.asList("default", "value")); 
25

由於default方法,Java的8現在有這個內置有Map::getOrDefault

Map<Integer, String> map = ... 
map.put(1, "1"); 
System.out.println(map.getOrDefault(1, "2")); // "1" 
System.out.println(map.getOrDefault(2, "2")); // "2" 
相關問題