前言
今天看 《Java8 实战》 发现了 Optional 可以用来改善工作中的代码质量。本文用于巩固 Optional 的 api 积累及理解,并尝试多多应用于生产中。
给出一个简单的编码场景:
// 模拟VO
Insurance insurance = new Insurance();
// 模拟字段的数据源,通常是为了节省数据库IO, 由全量数据转化成的 key-value
HashMap<String, String> properties = new HashMap<>();
properties.put("nameA", "1.8");
properties.put("nameB", "2.2");
// VO补充字段信息
String insuranceName = insurance.getName();
if (StringUtils.isNotBlank(insuranceName)) {
String price = properties.get(insuranceName);
if (StringUtils.isNotBlank(price)) {
try {
insurance.setPrice(new BigDecimal(price));
} catch (Exception e) {
// 省略
}
}
}
优化后的效果
结合《Java8 实战》可以得到一个优化的vo赋值代码。
// VO补充字段信息
insurance.setPrice(readAmount(properties, insurance.getName()));
readAmount 背后做的努力
public BigDecimal readAmount(Map<String, String> properties, String name) {
return Optional.ofNullable(properties)
.map(p -> p.get(name))
.flatMap(OptionalUtil::stringToBigDecimal)
.filter(i -> i.compareTo(BigDecimal.ZERO) > 0)
.orElse(BigDecimal.ZERO);
}
- BigDecimal 的一个工具类(随手写的)
public class OptionalUtil {
public static Optional<BigDecimal> stringToBigDecimal(String s) {
Optional<BigDecimal> ret;
try {
ret = Optional.of(new BigDecimal(s));
} catch (Exception e) {
return Optional.empty();
}
return ret;
}
}
涉及的 Optional Api 积累
Optional.empty()
返回一个“空的” Optional 对象,使用该对象调用其他api不会报空指针
Optional.ofNullable(properties)
可以用来承载一个非空值,如果传入空值时为 Optional.empty(),上文传入非空则为 Optional<Map<String, String>>
Optional.map(p -> p.get(name))
结合声明来理解,表示一个流
T ----> mapper 处理 -----> U
映射到上文的逻辑框架
Map<String, String> ----> mapper 处理 ----> mapper 的返回值
加入框架
Optional.map(p -> p.get(name))
的参数就是 Map<String, String>
Optional.flatMap(OptionalUtil::stringToBigDecimal)
把 Optional 内的 String 还可以拆解出来转化,再放到Optional 内,这里就是把 String 变成 BigDecimal
orElse(BigDecimal.ZERO)
取Optional 内的内容,为empty时候则返回指定值。上文指定值为 BigDecimal.ZERO
后记
Optional 本质上就是个容器,由 Optional.empty() 代替null, 并且Optional.empty() 也具有链式调用的api,使得可以消灭判空语句。但是理解上还是需要一些成本。再接再厉,希望结合好的实践再加以巩固。