[英]How does java.util.Map's getOrDefault() work?
我注意到,如果我執行 map.getOrDefault("key1", new Object()),即使地圖中的key1
存在對象,也會創建new Object()
。 雖然它不是由該方法返回的,但它仍然會創建它。 例如,
public class Empl {
private int id;
private String name;
public Empl(String name) {
// TODO Auto-generated constructor stub
System.out.println(name);
this.name = name;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return name+id;
}
}
運行以下,
Map<String, Empl> map = new HashMap<String, Empl>();
Empl imp = new Empl("timon");
map.put("1", imp);
System.out.println(map.getOrDefault("1", new Empl("dumnba")));
給出這個輸出:
timon
dumnba
timon0
是否應該僅在地圖中不存在默認對象時才創建默認對象? 如果不是,是什么原因?
是否應該僅在地圖中不存在默認對象時才創建默認對象?
怎么會這樣呢? 這個電話:
map.getOrDefault("1", new Empl("dumnba"))
相當於:
String arg0 = "1";
Empl arg1 = new Empl("dumnba");
map.getOrDefault(arg0, arg1);
換句話說,所有參數在傳遞給方法之前都經過評估。
您可能會改用computeIfAbsent
,但如果密鑰不存在,這將修改映射,您可能不希望這樣:
System.out.println(map.computeIfAbsent("1", k -> new Empl("dumnba")));
函數的所有參數都在函數執行之前進行評估。 Java 需要評估new Empl("dumnba")
以便將結果傳遞給getOrDefault
。 在調用getOrDefault
之前,它無法知道不需要其中一個參數。
如果要提供除非需要才計算的默認值,可以使用computeIfAbsent
。 為此,您傳入一個函數,該函數僅在需要默認值時執行。
map.computeIfAbsent("1", key -> new Empl("dumnba"))
查看java 8實現:
default V getOrDefault(Object key, V defaultValue) {
V v;
return (((v = get(key)) != null) || containsKey(key))
? v
: defaultValue;
}
該文檔指定:
返回指定鍵映射到的值,如果此映射不包含鍵的映射,則返回defaultValue 。 故障
它將返回地圖中不存在的默認值
例子:
Map<String, String> map = new HashMap<>();
map.put("1", "Foo");
//search for the entry with key==1, since present, returns foo
System.out.println(map.getOrDefault("1", "dumnba"));
//search for the entry with key==2, since not present, returns dumnba
System.out.println(map.getOrDefault("2", "dumnba"));
這不是因為地圖的實現方式,而是因為 Java 的工作方式。 運行時解釋器必須先創建對象( new Empl
的 Empl 部分),然后才能實際調用該方法( getOrDefault
部分)。
從 Java 8 開始,如果你想避免計算默認參數,你可以使用 Optional 的 orElseGet 方法:
System.out.println(Optional.ofNullable(map.get("1"))
.orElseGet(() -> new Empl("dumnba")));
如果找到鍵“1”,orElseGet 將返回相應地圖的值。 否則它將返回評估傳遞的函數的結果。 僅當未找到密鑰時才會對其進行評估(並實例化類 Empl)。
當然,這將始終在找到密鑰時實例化一個 Optional。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.