我是Java新手,仍然在学习Optional。我知道它用于避免Null Pointer Exception。
我有一段代码要使用可选的,就像这样:
final MetadataExtractor<FCAddress> metadataExtractor = t -> {
final Map<String, String> metadata = new HashMap<>();
metadata.put("senderCountryCode", t.getCountryCode());
metadata.put("senderState", t.getState());
metadata.put("senderPostalCode",t.getPostalCode());
return metadata;
};
在这里,我的用例是,如果SenderState为空,即t.getState()为空,我希望map字段为空,即不填充。
我尝试过这样的事情:
final MetadataExtractor<FCAddress> metadataExtractor = t -> {
final Map<String, String> metadata = new HashMap<>();
metadata.put("senderCountryCode", t.getCountryCode());
Optional<String> senderState = Optional.of(t.getState());
senderState.ifPresent(metadata.put("senderState", t.getState());
metadata.put("senderPostalCode",t.getPostalCode());
return metadata;
};
但是这会导致编译错误,我在哪里出错呢? 错误是:“ ifPresent (java.util.function.Consumer) 不能应用”。
答案 0 :(得分:3)
您需要将使用者(lambda)传递给ifPresent:
senderState.ifPresent(state -> metadata.put("state", state);
// important: the Consumer always receive a parameter.
// An empty value `() ->` is not valid!
只有在senderState 存在(也就是说,不为null)的情况下,lambda才会被执行。
顺便说一句,使用senderState
构建Optional.ofNullable(...)
非常重要!否则,它将引发NPE。
答案 1 :(得分:2)
仍在学习Optionals。我了解它用于避免Null Pointer Exception。
不一定。它们是 mean ,它使您可以拥有表示“ nothing”的 something 。
关于实际的编译错误:
senderState.ifPresent(metadata.put("senderState", t.getState());
ifPresent()
想要消费者。来自javadoc:
public void ifPresent(Consumer<? super T> consumer)
如果存在值,则使用该值调用指定的使用者,否则不执行任何操作。
metadata.put()不是使用者。那是那个地图上的普通方法调用!它将返回地图的“值”类型,即String。字符串不是消费者!
长话短说:如果您真的想在这里使用ifPresent()
,那么您可能希望传递一个lambda表达式(有关示例,请参见here)。
就您而言,
senderState.ifPresent(state -> metadata.put("senderState", state));
应该做。
答案 2 :(得分:2)
在此特定代码中,Optional
的使用无济于事,因为您不希望向地图添加Optional
,而只跳过null
值。
不创建新对象的最简单解决方案是添加t.getState()
值检查,如下所示:
final MetadataExtractor<FCAddress> metadataExtractor = t -> {
final Map<String, String> metadata = new HashMap<>();
metadata.put("senderCountryCode", t.getCountryCode());
if (t.getState() != null) {
metadata.put("senderState", t.getState());
}
metadata.put("senderPostalCode",t.getPostalCode());
return metadata;
};
出于研究目的, GhostCat 的解决方案与Optional
一起使用:
senderState.ifPresent(() -> metadata.put("senderState", t.getState());
完整的示例将是:
final MetadataExtractor<FCAddress> metadataExtractor = t -> {
final Map<String, String> metadata = new HashMap<>();
metadata.put("senderCountryCode", t.getCountryCode());
// Here you create a not useful object that can be replaced with a simple if
Optional<String> senderState = Optional.ofNullable(t.getState());
// Here you create a second not necessary object because a lambda
// espression is an instance of an anonimous class implementing
// the corresponding interface
senderState.ifPresent(() ->
metadata.put("senderState", t.getState()
);
metadata.put("senderPostalCode",t.getPostalCode());
return metadata;
};
请注意,此解决方案将创建两个不必要的对象:
Optional
senderState
Consumer
对象,该对象在ifPresent
方法内被创建为lambda表达式答案 3 :(得分:2)
仅提供一种完全不同的方法来解决该问题:
将所有内容放入地图,然后在以下位置删除空值:
metadata.values().removeIf(Objects::isNull);
从语法上讲,这很整洁,但是由于先做某事然后撤消它,而不是一开始就不做,这可能会更快,也可能不会更快。