从包装在Java可选文件中的对象提取多个字段
这个问题类似于Java而不是Scala 假设我有一个返回从包装在Java可选文件中的对象提取多个字段,java,optional,Java,Optional,这个问题类似于Java而不是Scala 假设我有一个返回可选值的方法。 我需要从包装的地址中提取多个字段,例如getCity(),getCountry(),和getZIP()。如果地址不存在,则应使用一些默认值。然后,逻辑应继续处理结果值 问题是这样做的最佳和最惯用的方式是什么。我可以想到以下三点: 1)如果有其他情况 城市; 国家; 拉链; 可选的optAddr=getAddress(); if(optAddr.isPresent()){ 地址addr=optAddr.get(); city=
可选值的方法。
我需要从包装的地址中提取多个字段,例如getCity()
,getCountry()
,和getZIP()
。如果地址不存在,则应使用一些默认值。然后,逻辑应继续处理结果值
问题是这样做的最佳和最惯用的方式是什么。我可以想到以下三点:
1)如果有其他情况
城市;
国家;
拉链;
可选的optAddr=getAddress();
if(optAddr.isPresent()){
地址addr=optAddr.get();
city=addr.getCity();
country=addr.getCountry();
zip=addr.getZIP();
}
否则{
城市=空;
country=country.getUSA();
zip=zip.DEFAULT;
}
// ... 使用城市、国家和邮政编码
优点:
- 没有创建额外的对象-最有效的变体
- 默认情况分组在一起
缺点:
- 冗长的
2)多条链
可选optAddr=getAddress();
City-City=optAddr.map(地址::getCity()
.orElse(空);
Country Country=optAddr.map(地址::getCountry)
.orElseGet(国家:getUSA);
ZIP=optAddr.map(地址::getZIP)
.orElse(ZIP.DEFAULT);
//…使用城市、国家和邮政编码
请注意,这里的逻辑略有不同,因为默认值不仅在缺少地址时适用,而且在相应的地址字段为null
时也适用
但这不是我的问题
优点:
- 简洁
- 变量立即初始化为一个值
- 更接近于如何使用单个字段完成
缺点:
- 默认值是分散的
- 对
map
的链式调用可能会创建中间对象(但以惯用的方式)
- 可能在单个
可选上使用多条链
3a)将默认值包装到对象中
专用地址createDefaultAddress(){
地址addr=新地址();
地址设置城市(空);
地址setCountry(Country.getUSA());
addr.setZIP(ZIP.DEFAULT);
返回地址;
}
地址addr=getAddress().orelsGet(this::createDefaultAddress);
City-City=addr.getCity();
Country Country=addr.getCountry();
ZIP=addr.getZIP();
// ... 使用城市、国家和邮政编码
优点:
- 清晰
缺点:
- 字段被打包到一个
地址中
,仅用于随后立即提取它们
3b)将默认值包装为常量
正如@HariMenon和@flakes所建议的那样,具有默认值的an地址可以存储在常量中,并在每次调用中重复使用,以减少开销
还可以延迟初始化该“常量”:
私有地址默认地址;
私有地址getDefaultAddress(){
if(defaultAddress==null){
defaultAddress=新地址();
defaultAddress.setCity(空);
defaultAddress.setCountry(Country.getUSA());
defaultAddress.setZIP(ZIP.DEFAULT);
}
返回默认地址;
}
地址addr=getAddress().orelsGet(this::getDefaultAddress);
// ... 与3.1相同
奖金问题:
假设我完全控制getAddress()
方法,并且我知道所有用法都与本例类似,但默认值不同。
我是否应该将其更改为返回null
而不是可选
,以更好地适应if else
解决方案?这有点主观,因此不会有正确的答案。但这是我的2美分,以及我为什么这么认为。选项1绝对不是Java8的惯用方法
在2和3之间,您将选择什么取决于您是希望使用默认地址,还是希望使用单独的默认城市、国家和邮政编码。如果地址不为空,但城市为空,是否仍要使用默认城市?选择3会让事情变得丑陋。否则,我倾向于选择3。即使您将其包装到一个对象中,该对象也可以是一个名为DEFAULT_ADDRESS的常量,然后它会变得非常清楚它到底是什么,因此更具可读性
选项2使它看起来就像您有一个单独的默认国家、城市和邮政编码,而事实似乎并非如此。但是就像我说的,如果是这样的话,你应该用它
编辑3b和奖金:
若您正在考虑包装器对性能的影响,那个么您就想得太多了。在Java中创建这样的包装器非常便宜,而现代JIT编译器在大多数情况下都能很好地优化这一点。可读性优于性能,除非通过测量证明代码是性能瓶颈。对于可选vs null,只需选择一种编码样式并在项目中使用它
如果您正在返回Optionals,那么请确保该方法从不返回null(可以同时返回Optional和null的方法是令人讨厌的)。许多人认为您应该始终使用Optional
s。就我个人而言,我有点不同意。如果它是一个新的代码库,并且我们在任何地方都使用Optionals,那么它就很棒了。坚持使用它,不要在任何地方使用null和null检查。如果它是一个已经在多个位置使用null的旧代码库,那么只需使用null并记录该方法在某些情况下可以返回null。将可选项和空项组合在一起会造成可怕的混乱,我认为可选项的好处不足以超过成本。Optionals在从一开始就支持它们的语言中非常好。但他们
private static final Address DEFAULT_ADDRESS = new Address() {{
setCity(null);
setCountry(Country.getUSA());
setZIP(ZIP.DEFAULT);
}};
...
Address addr = getAddress().orElse(DEFAULT_ADDRESS);