10.4 使用Optional的实战示例
10.4.1 用Optional封装可能为null的值
通过Optiona封装方法的返回值,实现潜在为null对象的安全转换
Object value = map.get("key");
// 重构
Optional<Object> value = Optional.ofNullable(map.get("key"));
10.4.2 异常与Optional的对比
在函数无法返回有效值时,除了返回null,还有抛出异常的情形。
通过try-catch捕获函数异常,返回Optional.empty()
public static Optional<Integer> stringToInt(String s) {
try {
return Optional.of(Integer.parseInt(s));
} catch (NumberFormatException e) {
return Optional.empty();
}
}
基础类型的Optional对象,以及为什么应该避免使用它们
Optional跟Stream类似,对于Optional
泛型Optional | 基础类型Optional | 泛型Stream | 基础类型Stream |
---|---|---|---|
Optional |
OptionalInt | Stream |
IntStream |
Optional |
OptionalLong | Streaml |
LongStream |
Optional |
OptionalDouble | Stream |
DoubleStream |
若Stream对象包含了大量元素,出于性能的考量,使用基础类型,但对Optional对象而言,至多包含一个值,这个理由就不成立了。
基础类型Optional无法跟泛型Optional组合使用,不支持map、flatMap以及filter方法,因此出于便利性,不推荐使用基础类型的Optional。
10.4.3 把所有内容整合起来
展示之前介绍过的Optional类的各种方法整合在一起的效果。
public Properties buildProperties() {
Properties props = new Properties();
props.setProperty("a", "5");
props.setProperty("b", "true");
props.setProperty("c", "-3");
return props;
}
public static int readDuration(Properties properties, String name) {
String value = properties.getProperty(name);
try {
int result = Integer.parseInt(value);
if (result > 0) {
return result;
}
} catch (NumberFormatException ignored) {
}
return 0;
}
@Test
public void testReadDuration() {
Properties param = buildProperties();
Assert.assertEquals(5, readDuration(param, "a"));
Assert.assertEquals(0, readDuration(param, "b"));
Assert.assertEquals(0, readDuration(param, "c"));
Assert.assertEquals(0, readDuration(param, "d"));
}
测验10.3:使用Optional从属性中读取duration
受前面的测验影响,写得复杂了些
public static int readDuration(Properties properties, String name) {
return Optional.ofNullable(properties).flatMap(props -> OptionalUtility.stringToInt(props.getProperty(name)))
.filter(value -> value >= 0).orElse(0);
}
更简洁版
public static int readDuration(Properties properties, String name) {
return Optional.ofNullable(properties.getProperty(name)).flatMap(OptionalUtility::stringToInt)
.filter(value -> value >= 0).orElse(0);
}
Optional和Stream时的这些通用模式,都是对数据库查询过程的反思,查询时,多种操作会被串接在一起执行。
-
实际在互联网业务开发中,为降低数据库的负载,通用做法是执行简单SQL语句,由后端实现复杂逻辑的运算;
-
大数据写离线任务,可以执行复杂的SQL逻辑运算;