簡體   English   中英

java.util.Map 的 getOrDefault() 是如何工作的?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM