Java 8 可选添加仅在 optional.isPresent 时返回结果
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37846407/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java 8 optional add return result only if optional.isPresent
提问by Vale
I have a piece of code where an interface has an Optional return method and some of the classes that implement it to return something, other don't.
我有一段代码,其中一个接口有一个 Optional 返回方法和一些实现它以返回某些东西的类,其他的则没有。
In an effort to embrace this brilliant "null killer", here is what I have tried:
为了拥抱这个出色的“零杀手”,这是我尝试过的:
public interface Gun {
public Optional<Bullet> shoot();
}
public class Pistol implements Gun{
@Override
public Optional<Bullet> shoot(){
return Optional.of(this.magazine.remove(0));
}//never mind the check of magazine content
}
public class Bow implements Gun{
@Override
public Optional<Bullet> shoot(){
quill--;
return Optional.empty();
}
}
public class BallisticGelPuddy{
private Gun[] guns = new Gun[]{new Pistol(),new Bow()};
private List<Bullet> bullets = new ArrayList<>();
public void collectBullets(){
//here is the problem
for(Gun gun : guns)
gun.shoot.ifPresent(bullets.add( <the return I got with the method>)
}}
I apologise for how silly this example is.
How can I check the return I just got and add it only if present, using optional?
我为这个例子有多愚蠢而道歉。
如何检查我刚刚得到的回报并仅在存在时添加它,使用可选?
P.S. is there any real usefulness to Optional which is if(X != null) couldn't do?
PS Optional 是否有任何真正的用处,即 if(X != null) 不能做?
回答by Makoto
I see where you're going with this - when a projectile (may be a better class name than Bullet
) goes through BallisticGelPuddy
, it either becomes stuck or it doesn't. If it gets stuck, it accumulates in BallisticGelPuddy
.
我知道你要做什么 - 当一个射弹(可能是一个比 更好的类名Bullet
)通过时BallisticGelPuddy
,它要么被卡住,要么不会卡住。如果它被卡住,它会在 中积累BallisticGelPuddy
。
Let's rewrite the code if we were using null
checks instead:
如果我们改用null
检查,让我们重写代码:
for(Gun gun: guns) {
final Bullet bullet = gun.shoot();
if(bullet != null) {
bullets.add(bullet);
}
}
Pretty straightforward, right? If it exists we want to add it in.
很简单吧?如果它存在,我们想把它添加进去。
Let's add the optional style back in:
让我们重新添加可选样式:
for(Gun gun: guns) {
gun.shoot().ifPresent(bullets::add);
}
Effectively these two things accomplish the same thing, although the Optional
approach is terser.
尽管Optional
方法更简洁,但这两件事实际上可以完成相同的事情。
In this scenario, there's really no difference between the two approaches since you're always going to be checking for existence. Optional
is meant to guard against mistakes when handling null
and allows you to express a more fluid call chain, but consider the practicality of using Optional
in this scenario. It doesn't seem entirely necessaryfor this case.
在这种情况下,这两种方法之间确实没有区别,因为您总是要检查是否存在。 Optional
旨在防止处理时出错,null
并允许您表达更流畅的调用链,但请考虑Optional
在这种情况下使用的实用性。对于这种情况,这似乎并不完全必要。
回答by Bohemian
I think you want:
我想你想要:
gun.shoot().ifPresent(bullets::add);
Or you can dispense with the (coded) loop too:
或者您也可以省去(编码)循环:
guns.stream()
.map(Gun::shoot)
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(bullets::add);
But it's uglier.
但它更丑。
回答by user140547
With the stream API, you can do:
使用流 API,您可以执行以下操作:
List<Bullet> bullets = Arrays.stream(guns)
.map(Gun::shoot)
.flatMap(this::streamopt) // make Stream from Optional!
.collect(Collectors.toList());
Unfortunately, in Java 8, there is no method which converts Optionals to Stream, so you need to write it yourself. See Using Java 8's Optional with Stream::flatMap
不幸的是,在 Java 8 中,没有将 Optionals 转换为 Stream 的方法,因此您需要自己编写。请参阅在 Stream::flatMap 中使用 Java 8 的 Optional
回答by Vale
I want to post this for future reference, for anybody tripping in a problem similar to mine. Should you want access to methods of what you have just returned, if present:
我想发布此内容以供将来参考,以供任何与我类似的问题绊倒的人。如果您想访问刚刚返回的方法(如果存在):
public class Bullet{
private int weight = 5;
public int getWeight(){ return weigth;}
}
public interface Gun {
public Optional<Bullet> shoot();
}
public class Pistol implements Gun{
@Override
public Optional<Bullet> shoot(){
return Optional.of(this.magazine.remove(0));
}//never mind the check of magazine content
}
public class Bow implements Gun{
@Override
public Optional<Bullet> shoot(){
quill--;
return Optional.empty();
}
}
public class BallisticGelPuddy{
private Gun[] guns = new Gun[]{new Pistol(),new Bow()};
private List<Bullet> bullets = new ArrayList<>();
private int totWeigth = 0;
public void collectBullets(){
// IF YOU WANT TO ONLY ADD WHAT YOU HAVE FOUND IN A COMPATIBLE CLASS
// thanks to makoto and bohemian for the answers
for(Gun gun : guns)
gun.shoot.ifPresent(bullets::add)
//IF YOU WANT TO ACCESS THE RETURNED OBJECT AND ADD IT TOO
for(Gun gun : guns)
gun.shoot.ifPresent( arg -> {totWeight += arg.getWeigth();
bullets.add(arg);});
}}