java-空字符串的Optional实现
作者:互联网
Optional最好的事情之一是,它保存了所有检查样板的长链中的空值:
Optional.ofNullable(myService.getSomething())
.map(secondService::fetch)
.map(thirdService::fetchAgain)
// And so forth...
如果地图返回null,则Optional在任何时候都将跳到“空”轨道.
如果可以对String进行类似的操作,而不必每次都检查String :: isEmpty,那就太好了:
Optional.ofNullable(entity.getName())
.filter(String::isEmpty)
.map(Utils::performSomeOperation)
.filter(String::isEmpty)
.or(service::getMostCommonName)
.filter(String::isEmpty)
.orElse("Bob");
像这样:
OptionalString.ofEmptyable(entity.getName())
.map(Utils::performSomeOperation)
.or(service::getMostCommonName)
.orElse("Bob");
当Optional的关键逻辑调用其对value == null的检查时,它发生在ofNullable中.从理论上讲,您可以在其中应用任何形式的逻辑:
MagicalOptionalString(StringUtils::isNotBlank).ofEmptyable(entity.getName())
.map(Utils::performSomeOperation)
.or(service::getMostCommonName)
.orElse("Bob");
但是,Optional是最终的,阻止了任何直接的方式扩展这种行为.那么,已经有一个强大的现有实现方案了吗?
解决方法:
尝试一些事情来解决您的目标,然后意识到我会从VGR那里接受想法,因为与使用现有方法相比,实现这种用例是很多额外的工作.
但是,在花一些时间查看实现之后,我可以添加的细节很少-
作为实用程序,您可以实现一个静态实现,该实现将验证字符串输入的null和isEmpty条件,并相应地返回Optional.该代码可能看起来像-
private static Optional<String> ofEmptyable(String string) {
return isNullOrEmpty(string) ? Optional.empty() : Optional.of(string);
}
private static boolean isNullOrEmpty(String target) {
return target == null || target.isEmpty();
}
然后,这可以代替ofNullable的用法,后者专门检查null(Optional的主要目的).
由于问题陈述中的期望是像可选方法一样实际处理每个方法(map / or /或Else)调用的情况,因此与OptionalInt类似的一种方法可以是将自定义OptionalString实现为-
public final class OptionalString {
private static final OptionalString EMPTY = new OptionalString();
private final boolean isPresent;
private final String value;
private OptionalString() {
this.isPresent = false;
this.value = "";
}
private static OptionalString empty() {
return EMPTY;
}
private boolean isPresent() {
return isPresent;
}
private OptionalString(String value) {
this.isPresent = true;
this.value = value;
}
public static OptionalString of(String value) {
return value == null || value.isEmpty() ? OptionalString.empty() : new OptionalString(value);
}
public OptionalString map(Function<? super String, ? extends String> mapper) {
return !isPresent() ? OptionalString.empty() : OptionalString.of(mapper.apply(this.value));
}
public OptionalString or(Supplier<String> supplier) {
return isPresent() ? this : OptionalString.of(supplier.get());
}
String orElse(String other) {
return isPresent ? value : other;
}
public String getAsString() {
return Optional.of(value).orElseThrow(() -> new NoSuchElementException("No value present"));
}
}
可以通过以下方式针对您的用例进一步实现-
String customImpl = OptionalString.of(entity.getName())
.map(OptionalStringTest::trimWhiteSpaces) // OptionalStringTest is my test class name where 'trimWhiteSpaces' operation on String resides
.or(service::getMostCommonName)
.orElse("learning");
System.out.println(String.format("custom implementation - %s", customImpl));
哪里
private static String trimWhiteSpaces(String x) {
return x.trim();
}
注意-老实说,我找不到JDK中没有OptionalString类的背后的理由(我之所以这样说是因为我怀疑背后肯定有想法),我相信这仅仅是因为我的触角半径要小得多,我希望有人能在这里添加更多细节.恕我直言,看起来几乎所有您想要的东西都在使用Optional< String>这将我们带回到循环的开始.
标签:optional,java-9,string,java 来源: https://codeday.me/bug/20191108/2009484.html