我非常想使用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));
(命名参数k
或key
都没有关系)。如果whoLetDogsOut.computeIfAbsent("snoop", MyClass::tryToLetOut);
是tryToLetOut
,则将其写为static
;如果whoLetDogsOut.computeIfAbsent("snoop", this::tryToLetOut);
是实例方法,则将其写为tryToLetOut
。