如何在避免 NoSuchElementException 错误的同时获取可选值?
How to get optional value while avoiding NoSuchElementException error?
我有以下代码
private static String getAddressLine(Addresses addresses) {
if (addresses.getAddrCivicNo() == null || addresses.getStName() == null)
{
return null;
}
StringBuilder addressLine = new StringBuilder("");
addressLine.append(Optional.ofNullable(addresses.getAddrCivicNo()).get());
addressLine.append(" ");
addressLine.append(Optional.ofNullable(addresses.getAddrPreStrTypeDesignator()).get());
addressLine.append(" ");
addressLine.append(Optional.ofNullable(addresses.getStName()).get());
addressLine.append(", ");
addressLine.append(Optional.ofNullable(addresses.getAddrPostStrTypeDesignator()).get());
addressLine.append(" ");
addressLine.append(Optional.ofNullable(addresses.getAddrPostStrDirectionDesignator()).get());
addressLine.append(" ");
addressLine.append(Optional.ofNullable(addresses.getAddrPreStrDirectionDesignator()).get());
addressLine.append(" ");
addressLine.append(Optional.of(addresses.getAddrUnitDesignatorTypeCd()).get());
addressLine.append(" ");
addressLine.append(Optional.of(addresses.getAddrUnitNo()).get());
return addressLine.toString();
}
如果我的任何字段是 null
,由于 get()
调用,我会收到 NoSuchElementException
错误。如果我删除 get()
调用,我将追加 Optional.empty
,但如果字段是 null
,我不想追加任何内容。有什么建议吗?
您可以使用默认值,例如空 String
:
private static final String DEFAULT_FIELD = "";
Optional.ofNullable(addresses.getAddrCivicNo()).orElse(DEFAULT_FIELD)
尽管如果不需要可空值的映射,检查 null 然后解析(可能使用 ?:
运算符)会更清晰。
您也可以尝试标准化这些值。我认为这里的 Optional
"monad" 没有任何价值。
这样的事情应该有效(仅适用于 String
值):
public static String nullToEmpty(final String str) {
return (null == str) ? "" : str;
}
// ...
nullToEmpty(addresses.getAddrCivicNo());
使用 Objects.toString 方法,该方法采用“如果第一个参数为空则使用”参数:
addressLine.append(Objects.toString(addresses.getAddrCivicNo(), ""));
addressLine.append(" ");
addressLine.append(Objects.toString(addresses.getAddrPreStrTypeDesignator(), ""));
addressLine.append(" ");
addressLine.append(Objects.toString(addresses.getStName(), ""));
addressLine.append(", ");
addressLine.append(Objects.toString(addresses.getAddrPostStrTypeDesignator(), ""));
addressLine.append(" ");
addressLine.append(Objects.toString(addresses.getAddrPostStrDirectionDesignator(), ""));
addressLine.append(" ");
addressLine.append(Objects.toString(addresses.getAddrPreStrDirectionDesignator(), ""));
addressLine.append(" ");
addressLine.append(addresses.getAddrUnitDesignatorTypeCd());
addressLine.append(" ");
addressLine.append(addresses.getAddrUnitNo());
如果您使用的是 JDK9+,我建议您查看 Objects.requireNonNullElse 即:
public static <T> T requireNonNullElse(T obj,T defaultObj)
这比 Optional.ofNullable(addresses.getAddrCivicNo()).orElse(...)
等更简洁、更易读。使用前者对性能更友好,因为您不需要创建可选实例。
此外,一些想法可能 简化您的逻辑。
您可以使用 Stream.of
,然后过滤掉空值,然后使用指定的分隔符连接。
Stream.of(addresses.getAddrCivicNo(), addresses.getAddrPreStrTypeDesignator(), ...)
.filter(Objects::nonNull)
.collect(joining(" "));
我建议您考虑的另一个建议是可能使用函数 getAddressLine
return 和 Optional<String>
而不是 String
。这实质上使这个 API 的客户端不处理 nullity 而是给他们可选的 API 来操作,它提供了几个有用的方法来解包 Optional安全。
我有以下代码
private static String getAddressLine(Addresses addresses) {
if (addresses.getAddrCivicNo() == null || addresses.getStName() == null)
{
return null;
}
StringBuilder addressLine = new StringBuilder("");
addressLine.append(Optional.ofNullable(addresses.getAddrCivicNo()).get());
addressLine.append(" ");
addressLine.append(Optional.ofNullable(addresses.getAddrPreStrTypeDesignator()).get());
addressLine.append(" ");
addressLine.append(Optional.ofNullable(addresses.getStName()).get());
addressLine.append(", ");
addressLine.append(Optional.ofNullable(addresses.getAddrPostStrTypeDesignator()).get());
addressLine.append(" ");
addressLine.append(Optional.ofNullable(addresses.getAddrPostStrDirectionDesignator()).get());
addressLine.append(" ");
addressLine.append(Optional.ofNullable(addresses.getAddrPreStrDirectionDesignator()).get());
addressLine.append(" ");
addressLine.append(Optional.of(addresses.getAddrUnitDesignatorTypeCd()).get());
addressLine.append(" ");
addressLine.append(Optional.of(addresses.getAddrUnitNo()).get());
return addressLine.toString();
}
如果我的任何字段是 null
,由于 get()
调用,我会收到 NoSuchElementException
错误。如果我删除 get()
调用,我将追加 Optional.empty
,但如果字段是 null
,我不想追加任何内容。有什么建议吗?
您可以使用默认值,例如空 String
:
private static final String DEFAULT_FIELD = "";
Optional.ofNullable(addresses.getAddrCivicNo()).orElse(DEFAULT_FIELD)
尽管如果不需要可空值的映射,检查 null 然后解析(可能使用 ?:
运算符)会更清晰。
您也可以尝试标准化这些值。我认为这里的 Optional
"monad" 没有任何价值。
这样的事情应该有效(仅适用于 String
值):
public static String nullToEmpty(final String str) {
return (null == str) ? "" : str;
}
// ...
nullToEmpty(addresses.getAddrCivicNo());
使用 Objects.toString 方法,该方法采用“如果第一个参数为空则使用”参数:
addressLine.append(Objects.toString(addresses.getAddrCivicNo(), ""));
addressLine.append(" ");
addressLine.append(Objects.toString(addresses.getAddrPreStrTypeDesignator(), ""));
addressLine.append(" ");
addressLine.append(Objects.toString(addresses.getStName(), ""));
addressLine.append(", ");
addressLine.append(Objects.toString(addresses.getAddrPostStrTypeDesignator(), ""));
addressLine.append(" ");
addressLine.append(Objects.toString(addresses.getAddrPostStrDirectionDesignator(), ""));
addressLine.append(" ");
addressLine.append(Objects.toString(addresses.getAddrPreStrDirectionDesignator(), ""));
addressLine.append(" ");
addressLine.append(addresses.getAddrUnitDesignatorTypeCd());
addressLine.append(" ");
addressLine.append(addresses.getAddrUnitNo());
如果您使用的是 JDK9+,我建议您查看 Objects.requireNonNullElse 即:
public static <T> T requireNonNullElse(T obj,T defaultObj)
这比 Optional.ofNullable(addresses.getAddrCivicNo()).orElse(...)
等更简洁、更易读。使用前者对性能更友好,因为您不需要创建可选实例。
此外,一些想法可能 简化您的逻辑。
您可以使用 Stream.of
,然后过滤掉空值,然后使用指定的分隔符连接。
Stream.of(addresses.getAddrCivicNo(), addresses.getAddrPreStrTypeDesignator(), ...)
.filter(Objects::nonNull)
.collect(joining(" "));
我建议您考虑的另一个建议是可能使用函数 getAddressLine
return 和 Optional<String>
而不是 String
。这实质上使这个 API 的客户端不处理 nullity 而是给他们可选的 API 来操作,它提供了几个有用的方法来解包 Optional安全。