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

时间:2017-05-02 11:44:43

标签: java

我注意到如果我执行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

只有在地图中没有默认对象时,才能创建默认对象吗?如果不是,原因是什么?

5 个答案:

答案 0 :(得分:20)

  

只有在地图中没有默认对象时,才能创建默认对象吗?

情况怎么可能?这个电话:

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")));

答案 1 :(得分:5)

在执行函数之前,会计算函数的所有参数。 Java需要评估new Empl("dumnba"),以便将结果传递给getOrDefault。在调用getOrDefault之前无法知道其中一个参数不是必需的。

如果您想提供未计算的默认值,除非需要,您可以使用computeIfAbsent。为此,您传入一个函数,只有在需要默认值时才会执行该函数。

map.computeIfAbsent("1", key -> new Empl("dumnba"))

答案 2 :(得分:2)

查看java 8实现:

default V getOrDefault(Object key, V defaultValue) {
    V v;
    return (((v = get(key)) != null) || containsKey(key))
        ? v
        : defaultValue;
}

doc指定:

  

返回指定键映射到的值,或   如果此地图不包含该键的映射,则 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"));

答案 3 :(得分:1)

这不是因为地图的实现方式,而是因为Java的工作原理。运行时解释器必须首先创建对象(new Empl部分)才能实际调用该方法(getOrDefault部分)。

答案 4 :(得分:0)

从 Java 8 开始,如果您想避免评估默认参数,您可以使用 Optional 的 orElseGet 方法:

System.out.println(Optional.ofNullable(map.get("1"))
    .orElseGet(() -> new Empl("dumnba")));

如果找到键“1” orElseGet 将返回对应的映射值。否则,它将返回评估传递函数的结果。仅当未找到键时,才会对其进行评估(并实例化 Empl 类)。

当然,当找到键时,这将始终实例化一个 Optional。