我非常想使用Map.computeIfAbsent,但是自从lambdas进入本科以来已经太久了。

几乎直接来自文档:它给出了做事的旧方法的示例:

Map<String, Boolean> whoLetDogsOut = new ConcurrentHashMap<>();
String key = "snoop";
if (whoLetDogsOut.get(key) == null) {
  Boolean isLetOut = tryToLetOut(key);
  if (isLetOut != null)
    map.putIfAbsent(key, isLetOut);
}


和新方法:

map.computeIfAbsent(key, k -> new Value(f(k)));


但在他们的示例中,我认为我不太“了解”。我将如何转换代码以使用新的lambda表达方式?

最佳答案

假设您有以下代码:

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class Test {
    public static void main(String[] s) {
        Map<String, Boolean> whoLetDogsOut = new ConcurrentHashMap<>();
        whoLetDogsOut.computeIfAbsent("snoop", k -> f(k));
        whoLetDogsOut.computeIfAbsent("snoop", k -> f(k));
    }
    static boolean f(String s) {
        System.out.println("creating a value for \""+s+'"');
        return s.isEmpty();
    }
}


然后,您将看到消息creating a value for "snoop"恰好一次,就像在computeIfAbsent的第二次调用中已经存在该键的值一样。 lambda表达式k中的k -> f(k)只是键的占位符(参数),地图将传递给您的lambda以计算值。因此,在示例中,键被传递给函数调用。

或者,您可以编写:whoLetDogsOut.computeIfAbsent("snoop", k -> k.isEmpty());,无需辅助方法即可达到相同的结果(但是此时您将看不到调试输出)。甚至更简单,因为它是对现有方法的简单委托,您可以编写:whoLetDogsOut.computeIfAbsent("snoop", String::isEmpty);此委托不需要编写任何参数。

为了更接近问题中的示例,您可以将其写为whoLetDogsOut.computeIfAbsent("snoop", key -> tryToLetOut(key));(命名参数kkey都没有关系)。如果whoLetDogsOut.computeIfAbsent("snoop", MyClass::tryToLetOut);tryToLetOut,则将其写为static;如果whoLetDogsOut.computeIfAbsent("snoop", this::tryToLetOut);是实例方法,则将其写为tryToLetOut

09-15 23:44