从 Java 返回可选 ifPresent()
Returning from Java Optional ifPresent()
我知道你不能从 ifPresent()
return 所以这个例子不起作用:
public boolean checkSomethingIfPresent() {
mightReturnAString().ifPresent((item) -> {
if (item.equals("something")) {
// Do some other stuff like use "something" in API calls
return true; // Does not compile
}
});
return false;
}
其中 mightReturnAString()
可以 return 有效字符串或空可选。我所做的工作是:
public boolean checkSomethingIsPresent() {
Optional<String> result = mightReturnAString();
if (result.isPresent()) {
String item = result.get();
if (item.equals("something") {
// Do some other stuff like use "something" in API calls
return true;
}
}
return false;
}
它更长,并且与首先检查空值没有太大区别。我觉得一定有更简洁的方式使用 Optional.
如何映射到布尔值?
public boolean checkSomethingIfPresent() {
return mightReturnAString().map(item -> {
if (item.equals("something")) {
// Do some other stuff like use "something" in API calls
return true; // Does not compile
}
return false; // or null
}).orElse(false);
}
我认为您要查找的只是 filter
然后检查是否存在:
return result.filter(a -> a.equals("something")).isPresent();
虽然@nullpointer 和@Ravindra 展示了如何将 Optional 与另一个条件合并,但您必须做更多的工作才能调用 API 并执行您在问题中提出的其他操作。在我看来,以下内容看起来非常可读和简洁:
private static boolean checkSomethingIfPresent() {
Optional<String> str = mightReturnAString();
if (str.filter(s -> s.equals("something")).isPresent()) {
//call APIs here using str.get()
return true;
}
return false;
}
更好的设计是链接方法:
private static void checkSomethingIfPresent() {
mightReturnFilteredString().ifPresent(s -> {
//call APIs here
});
}
private static Optional<String> mightReturnFilteredString() {
return mightReturnAString().filter(s -> s.equals("something"));
}
private static Optional<String> mightReturnAString() {
return Optional.of("something");
}
理想的解决方案是“命令查询分离”:创建一个方法(命令)来处理字符串(如果存在)。还有另一种方法(查询)告诉你它是否在那里。
然而,我们并没有生活在一个理想的世界中,完美的解决方案是永远不可能的。如果在您的情况下您不能将命令和查询分开,我的口味是 shmosel 已经提出的想法:映射到 boolean
。作为细节,我会使用 filter
而不是内部 if
语句:
public boolean checkSomethingIfPresent() {
return mightReturnAString().filter(item -> item.equals("something"))
.map(item -> {
// Do some other stuff like use "something" in API calls
return true; // (compiles)
})
.orElse(false);
}
我不喜欢它的是调用链有一个副作用,这通常不是预期的,除了 ifPresent
和 ifPresentOrElse
(和 orElseThrow
,当然)。
如果硬要用ifPresent
让副作用更清楚,那是可以的:
AtomicBoolean result = new AtomicBoolean(false);
mightReturnAString().filter(item -> item.equals("something"))
.ifPresent(item -> {
// Do some other stuff like use "something" in API calls
result.set(true);
});
return result.get();
我使用 AtomicBoolean
作为结果的容器,因为我们不允许从 lambda 中分配给原语 boolean
。我们不需要它的原子性,但它也没有坏处。
Link: Command–query separation 维基百科
顺便说一下,如果你真的想从 Optional 中获取值,请使用:
Optional<User> user = service.getCurrentUset();
return user.map(User::getId);
我知道你不能从 ifPresent()
return 所以这个例子不起作用:
public boolean checkSomethingIfPresent() {
mightReturnAString().ifPresent((item) -> {
if (item.equals("something")) {
// Do some other stuff like use "something" in API calls
return true; // Does not compile
}
});
return false;
}
其中 mightReturnAString()
可以 return 有效字符串或空可选。我所做的工作是:
public boolean checkSomethingIsPresent() {
Optional<String> result = mightReturnAString();
if (result.isPresent()) {
String item = result.get();
if (item.equals("something") {
// Do some other stuff like use "something" in API calls
return true;
}
}
return false;
}
它更长,并且与首先检查空值没有太大区别。我觉得一定有更简洁的方式使用 Optional.
如何映射到布尔值?
public boolean checkSomethingIfPresent() {
return mightReturnAString().map(item -> {
if (item.equals("something")) {
// Do some other stuff like use "something" in API calls
return true; // Does not compile
}
return false; // or null
}).orElse(false);
}
我认为您要查找的只是 filter
然后检查是否存在:
return result.filter(a -> a.equals("something")).isPresent();
虽然@nullpointer 和@Ravindra 展示了如何将 Optional 与另一个条件合并,但您必须做更多的工作才能调用 API 并执行您在问题中提出的其他操作。在我看来,以下内容看起来非常可读和简洁:
private static boolean checkSomethingIfPresent() {
Optional<String> str = mightReturnAString();
if (str.filter(s -> s.equals("something")).isPresent()) {
//call APIs here using str.get()
return true;
}
return false;
}
更好的设计是链接方法:
private static void checkSomethingIfPresent() {
mightReturnFilteredString().ifPresent(s -> {
//call APIs here
});
}
private static Optional<String> mightReturnFilteredString() {
return mightReturnAString().filter(s -> s.equals("something"));
}
private static Optional<String> mightReturnAString() {
return Optional.of("something");
}
理想的解决方案是“命令查询分离”:创建一个方法(命令)来处理字符串(如果存在)。还有另一种方法(查询)告诉你它是否在那里。
然而,我们并没有生活在一个理想的世界中,完美的解决方案是永远不可能的。如果在您的情况下您不能将命令和查询分开,我的口味是 shmosel 已经提出的想法:映射到 boolean
。作为细节,我会使用 filter
而不是内部 if
语句:
public boolean checkSomethingIfPresent() {
return mightReturnAString().filter(item -> item.equals("something"))
.map(item -> {
// Do some other stuff like use "something" in API calls
return true; // (compiles)
})
.orElse(false);
}
我不喜欢它的是调用链有一个副作用,这通常不是预期的,除了 ifPresent
和 ifPresentOrElse
(和 orElseThrow
,当然)。
如果硬要用ifPresent
让副作用更清楚,那是可以的:
AtomicBoolean result = new AtomicBoolean(false);
mightReturnAString().filter(item -> item.equals("something"))
.ifPresent(item -> {
// Do some other stuff like use "something" in API calls
result.set(true);
});
return result.get();
我使用 AtomicBoolean
作为结果的容器,因为我们不允许从 lambda 中分配给原语 boolean
。我们不需要它的原子性,但它也没有坏处。
Link: Command–query separation 维基百科
顺便说一下,如果你真的想从 Optional 中获取值,请使用:
Optional<User> user = service.getCurrentUset();
return user.map(User::getId);